zoukankan      html  css  js  c++  java
  • 一分钟教你知道乐观锁和悲观锁的区别

    http://blog.csdn.net/hongchangfirst/article/details/26004335

    http://www.cnblogs.com/ruiding/p/4430545.html


    悲观锁(Pessimistic Lock), 顾名思义,就是很悲观,每次去拿数据的时候都认为别人会修改,所以每次在拿数据的时候都会上锁,这样别人想拿这个数据就会block直到它拿到锁。传统的关系型数据库里边就用到了很多这种锁机制,比如行锁,表锁等,读锁,写锁等,都是在做操作之前先上锁。

    乐观锁(Optimistic Lock), 顾名思义,就是很乐观,每次去拿数据的时候都认为别人不会修改,所以不会上锁,但是在更新的时候会判断一下在此期间别人有没有去更新这个数据,可以使用版本号等机制。乐观锁适用于多读的应用类型,这样可以提高吞吐量,像数据库如果提供类似于write_condition机制的其实都是提供的乐观锁。



    共享锁&排它锁 || 乐观锁&悲观索

    1.共享锁只用于表级,排他锁用于行级。

    2.加了共享锁的对象,可以继续加共享锁,不能再加排他锁。加了排他锁后,不能再加任何锁。

    3.比如一个DML操作,就要对受影响的行加排他锁,这样就不允许再加别的锁,也就是说别的会话不能修改这些行。同时为了避免在做这个DML操作的时候,有别的会话执行DDL,修改表的定义,所以要在表上加共享锁,这样就阻止了DDL的操作。

    4.当执行DDL操作时,就需要在全表上加排他锁

    为什么需要锁(并发控制)?

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

    典型的冲突有:

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

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

    为了解决这些并发带来的问题。 我们需要引入并发控制机制。

    并发控制机制

    悲观锁:假定会发生并发冲突,屏蔽一切可能违反数据完整性的操作。[1]

    乐观锁:假设不会发生并发冲突,只在提交操作时检查是否违反数据完整性。[1] 乐观锁不能解决脏读的问题。

    乐观锁应用

    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

  • 相关阅读:
    day01-html
    Word中划线的方法(五种)
    关于获取请求参数并处理显示的总结
    确定目标,把握时间,创造机会,努力加油!(关于大三下学期人生规划浅谈)
    重载运算符(一个例子)
    关于连接数据库的那点总结(感觉挺好的)
    Ribbon负载均衡
    idea中一份代码模拟集群
    Eureka集群
    Eureka配置服务提供者、服务消费者、失效剔除和自我保护
  • 原文地址:https://www.cnblogs.com/suizhikuo/p/7485438.html
Copyright © 2011-2022 走看看