在大学的时候学习了JSP,其中使用JDBC进行数据库操作,有一个语句是Statement.ExecuteUpdate,这个语句执行一个SQL的更新操作(如delete,update,insert),返回所影响的行数。当返回0时,则表示没有更新任何行。我以为可以判断返回值是否大于0来判断更新是否成功,但是,下面的两种情况均返回0:
1:没有找到需要更新的数据 比如,我们进行update的时候,条件是id=5,但是id=5的数据不存在。这种情况下,更新是失败的,返回0,很正确。
2:要更新的数据和更新的值是完全一样的 比如,我们要对id=5的记录进行更新,把title变成hello。虽然这条记录存在,但是这条记录的title本来就是hello,那么,返回值也是0
这样就有个问题,当第2种情况发生时,从逻辑上讲,更新操作是成功的,你可以理解成title被重新覆盖了,不管它原来是不是hello,但是现在就被更新成hello了。
因此,如果要对Update进行是否更新成功的判断,就需要在Update之前,调用Statement.ExecuteQuery进行查询,如果能查询到记录,则表示更新会成功。ExecuteUpdate的返回值仅仅代表更新了多少行。
这样,一个Update操作就会执行2次SQL语句的,效率会降低。我当时就纳闷,为什么ExecuteUpdate对于第2种情况会不返回0,虽然从数据库的角度上,它是可以忽略更新这条记录,但是从逻辑的角度上看,这条记录被更新似乎更加合乎情理,返回大于0的值似乎更有意义。
不过,为什么基本上所有的编程语言,只要有类似的函数,都会在第2种情况返回0呢?最近,这个问题总算想通了,之所以返回0,其实是为了解决同步的问题。
举个例子,现在,著名的开心网要对菜园的功能进行扩展,不光是能让玩家种菜,还要能让玩家偷别人家的菜。我们的程序逻辑如下:
这段程序的逻辑没有任何问题。
好了,现在程序开始给玩家用了,有一颗超级无敌白金大青菜快成熟了,众玩家垂涎欲滴等着偷。成熟的那一刻,众玩家以瞬间的爆发力点击了鼠标左键,进行了偷菜。
假设有2个人A和B,几乎同时点击了鼠标,我们看服务器上程序的逻辑:
大家可以看到,现在的超级无敌白金大青菜总数变成了N+1了,无故多出了1颗,显然,这个结果是不对的,也不是我们想要的。
开心网的代码是用PHP开发的,PHP中可没有Java中的Synchronous关键字。如果用一个本地文件来实现锁的功能,服务器的运行效率就会大大打折。那么,我们如何高效的解决这个同步问题呢?这时候,执行Update返回所影响的行数就具有了超人般的意义了。
请看上面第2段中的粗体代码,在执行这个逻辑的时候,我们会得到的Update的返回值是0,因为在做这个操作之前,菜园里的蔬菜数量已经被更新成N-1了,所以这个更新操作会被忽略,这样,我们就可以在程序中加一个判断:如果更新的返回值是0,则表示偷菜失败,虽然Update是成功的。虽然B问菜园的时候是有菜的,但是偷的时候却没有了,那也表示B没有偷到。可见,返回所影响的行数是非常有意义的,对于并发量大的网站,可以好好利用这个返回值,能在保证效率的状态下,解决同步的问题。Ferris2009-05-04
posted on 2009-05-04 18:30 CoffeeCat 阅读(9237) 评论(1) 编辑 收藏 引用
谢谢 回复 更多评论
Powered by: IT博客 Copyright © CoffeeCat