乐观锁与悲观锁的区别

为何须要锁(并发控制)?html

在多用户环境中,在同一时间可能会有多个用户更新相同的记录,这会产生冲突。这就是著名的并发性问题。数据库

典型的冲突有:并发

l 丢失更新:一个事务的更新覆盖了其它事务的更新结果,就是所谓的更新丢失。例如:用户A把值从6改成2,用户B把值从2改成6,则用户A丢失了他的更新。性能

l 脏读:当一个事务读取其它完成一半事务的记录时,就会发生脏读取。例如:用户A,B看到的值都是6,用户B把值改成2,用户A读到的值仍为6。spa

为了解决这些并发带来的问题。 咱们须要引入并发控制机制。.net

并发控制机制

    最经常使用的处理多用户并发访问的方法是加锁。当一个用户锁住数据库中的某个对象时,其余用户就不能再访问该对象。加锁对并发访问的影响体如今锁的粒度上。好比,放在一个表上的锁限制对整个表的并发访问;放在数据页上的锁限制了对整个数据页的访问;放在行上的锁只限制对该行的并发访问。可见行锁粒度最小,并发访问最好,页锁粒度最大,表锁介于2者之间。htm

悲观锁:假定会发生并发冲突,屏蔽一切可能违反数据完整性的操做。[1]      悲观锁假定其余用户企图访问或者改变你正在访问、更改的对象的几率是很高的,所以在悲观锁的环境中,在你开始改变此对象以前就将该对象锁住,而且直到你提交了所做的更改以后才释放锁。悲观的缺陷是不管是页锁仍是行锁,加锁的时间可能会很长,这样可能会长时间的限制其余用户的访问,也就是说悲观锁的并发访问性很差。对象

乐观锁:假设不会发生并发冲突,只在提交操做时检查是否违反数据完整性。[1] 乐观锁不能解决脏读的问题。    乐观锁则认为其余用户企图改变你正在更改的对象的几率是很小的,所以乐观锁直到你准备提交所做的更改时才将对象锁住,当你读取以及改变该对象时并不加锁。可见乐观锁加锁的时间要比悲观锁短,乐观锁能够用较大的锁粒度得到较好的并发访问性能。可是若是第二个用户刚好在第一个用户提交更改以前读取了该对象,那么当他完成了本身的更改进行提交时,数据库就会发现该对象已经变化了,这样,第二个用户不得不从新读取该对象并做出更改。这说明在乐观锁环境中,会增长并发用户读取对象的次数。blog

 

     从数据库厂商的角度看,使用乐观的页锁是比较好的,尤为在影响不少行的批量操做中能够放比较少的锁,从而下降对资源的需求提升数据库的性能。再考虑汇集索引。在数据库中记录是按照汇集索引的物理顺序存放的。若是使用页锁,当两个用户同时访问更改位于同一数据页上的相邻两行时,其中一个用户必须等待另外一个用户释放锁,这会明显地下降系统的性能。interbase和大多数关系数据库同样,采用的是乐观锁,并且读锁是共享的,写锁是排他的。能够在一个读锁上再放置读锁,但不能再放置写锁;你不能在写锁上再放置任何锁。锁是目前解决多用户并发访问的有效手段。  索引

乐观锁应用

1.      使用自增加的整数表示数据版本号。更新时检查版本号是否一致,好比数据库中数据版本为6,更新提交时version=6+1,使用该version值(=7)与数据库version+1(=7)做比较,若是相等,则能够更新,若是不等则有可能其余程序已更新该记录,因此返回错误。

2.      使用时间戳来实现.

注:对于以上两种方式,Hibernate自带实现方式:在使用乐观锁的字段前加annotation: @Version, Hibernate在更新时自动校验该字段。

悲观锁应用

须要使用数据库的锁机制,好比SQL SERVER 的TABLOCKX(排它表锁) 此选项被选中时,SQL  Server  将在整个表上置排它锁直至该命令或事务结束。这将防止其余进程读取或修改表中的数据。

SqlServer中使用

Begin Tran
select top 1 @TrainNo=T_NO
         from Train_ticket   with (UPDLOCK)   where S_Flag=0

      update Train_ticket
         set T_Name=user,
             T_Time=getdate(),
             S_Flag=1
         where T_NO=@TrainNo
commit

咱们在查询的时候使用了with (UPDLOCK)选项,在查询记录的时候咱们就对记录加上了更新锁,表示咱们即将对此记录进行更新. 注意更新锁和共享锁是不冲突的,也就是其余用户还能够查询此表的内容,可是和更新锁和排它锁是冲突的.因此其余的更新用户就会阻塞.

结论

在实际生产环境里边,若是并发量不大且不容许脏读,可使用悲观锁解决并发问题;但若是系统的并发很是大的话,悲观锁定会带来很是大的性能问题,因此咱们就要选择乐观锁定的方法.

 

参考文档

[1]Concurrent Control http://en.wikipedia.org/wiki/Concurrency_control

[2] Oracle的悲观锁和乐观锁http://space.itpub.net/12158104/viewspace-374745

[3] timestamp应用——乐观锁和悲观锁【转】http://hi.baidu.com/piaokes/blog/item/9b0c6854e4909050564e00b3.html

相关文章
相关标签/搜索