数据库隔离级别 悲观琐,乐观锁
关于隔离级别这篇说的最好了:http://singo107.iteye.com/blog/1175084
我补充的是更新丢失的问题。
当然 所有事务串行情况下不可能出现这个问题。
但就像文章说的 Serializable级别几乎在实际项目中是不会出现的。
先看更新丢失的场景吧:其实都不用绝对并发就会出现。
比如同一件商品被在2个请求中分别被购买1件, 请求A取出库存是100,大于等于1,那么可以购买。请求B比请求A慢2秒进来,取出库存也是100,OK,也可以购买。
这时候经过大量的业务处理,比如花费了3秒钟,A把商品库存修改为 100-1 =99;
2秒后紧接着B也会执行完业务逻辑,修改库存也是把读到的库存减去1 100-1 =99。
很显然,正确结果应该是98。这就所谓的更新丢失,先更新的没起到作用(如果2次是修改不同字段,就是丢失)。
在非 Serializable 级别下,怎么解决这个问题呢。
悲观锁方法:悲观锁是数据库实现的,查询的时候在sql语句最后加上 for update关键字,会在读之后把这条锁住。其他事务甚至都不能读!其实相当于还是把事务弄成串行。。。很显然高并发下完全不可行。
乐观锁方法:乐观锁其实由程序来实现,每条记录修改后都带一条版本号,假如请求A读取到100的版本号是1,那么修改的时候检查下,当前版本号和读的版本号是不是一致,一致的话,可以修改。 修改成99后立即把该条记录的版本号变成2。
这时候B请求呢,发送修改命令的时候,提供的版本号还是1,和当前版本号2对不上,不允许修改。。。
用的CAS方法,其实这个方法极其常用,比如svn。。。
乐观锁的缺点。它不是数据库级别的,假使有另外一套程序也来操作这个数据,就管不了。为什么第一种方法叫悲观锁呢,因为他认为,每一次读数据都可会冲突,但是这终究还是少数情况。所以说他的世界观悲观。。。乐观锁就乐观多了。
恩,就补充这么多。