V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
xalilo
V2EX  ›  Java

mysql 悲观锁 乐观锁

  •  
  •   xalilo · 2019-08-27 10:20:59 +08:00 · 7792 次点击
    这是一个创建于 1947 天前的主题,其中的信息可能已经有所发展或是发生改变。

    mysql InnoDB 引擎,看了网上文章都说悲观锁影响并发导致性能不好,我一直理解不了。不管是悲观锁还是乐观锁一般都要包裹在事务中,悲观锁 for update 对索引条件也只是行锁,并不影响正常读。乐观锁的 update 语句本身也是锁,需要在事务提交后才释放。大家帮忙解释下呢,为啥说乐观锁比悲观锁性能更好?

    22 条回复    2019-08-28 22:51:19 +08:00
    EminemW
        1
    EminemW  
       2019-08-27 10:31:31 +08:00 via iPhone   ❤️ 2
    悲观锁是操作前就锁上,乐观锁是提交的时候判断能不能提交,你说哪个占用时间长
    xalilo
        2
    xalilo  
    OP
       2019-08-27 10:44:02 +08:00
    @EminemW
    正常的 select 不会受影响,只是对同样要修改的才需要 for update,悲观锁控制还能避免后续可能存在的一堆大量的业务逻辑的无效执行。
    xalilo
        3
    xalilo  
    OP
       2019-08-27 10:47:50 +08:00
    想了下:
    像库存扣减这种校验不为负的,需要多次修改,最后一次才会无效的用乐观。
    像单据状态这种,变化少,每次都是互斥的用悲观锁更好?
    sutra
        4
    sutra  
       2019-08-27 11:11:08 +08:00
    乐观锁并不需要“释放”。
    xalilo
        5
    xalilo  
    OP
       2019-08-27 11:19:45 +08:00
    @sutra update 语句本身也是有锁的,事务不提交,锁一直存在,为什么不需要释放?
    tabris17
        6
    tabris17  
       2019-08-27 11:27:33 +08:00
    乐观锁 update 不是锁,MVCC 了解一下
    ccagml
        7
    ccagml  
       2019-08-27 12:08:58 +08:00 via Android
    乐观锁不是根据一个数据版本号判断能不能更新?
    Takamine
        8
    Takamine  
       2019-08-27 12:43:09 +08:00 via Android
    乐观锁有很多种实现,最简单的实现就是什么也不做。
    哪个快。:doge:
    aliipay
        9
    aliipay  
       2019-08-27 13:06:44 +08:00
    个人认为,乐观锁适用于写少读多且写冲突后代价比较小的地方
    zhze93
        10
    zhze93  
       2019-08-27 13:09:11 +08:00
    我认为,乐观锁更多的是提高并发读的能力吧,同时尽量保证数据可靠性。
    fvckDaybyte2
        11
    fvckDaybyte2  
       2019-08-27 13:14:55 +08:00 via iPhone
    眼花缭乱的术语……
    xalilo
        12
    xalilo  
    OP
       2019-08-27 14:19:59 +08:00
    @tabris17 MVCC 大概意思我了解一点,两个事务,第一个 update 未提交,第二个事务的 update 是会阻塞等待的,这里肯定是有锁的。
    xalilo
        13
    xalilo  
    OP
       2019-08-27 14:41:32 +08:00
    @aliipay 悲观锁也不影响正常的读,能举个读多写少,很明显乐观比悲观好的例子吗
    tabris17
        14
    tabris17  
       2019-08-27 14:56:35 +08:00
    @xalilo 乐观锁不开启事务的啊,只是利用 update 的原子性而已,你要说锁是否存在,当然也存在,毕竟 cas 操作本身也是一种锁,但是粒度小,所以可以并发高
    angsheng
        15
    angsheng  
       2019-08-27 14:59:32 +08:00
    @zhze93 可能多核上乐观锁更好?
    DonaldY
        16
    DonaldY  
       2019-08-27 14:59:49 +08:00


    其实 update 也可以自动 commit

    乐观锁是根据版本更新,即会 commit
    xalilo
        17
    xalilo  
    OP
       2019-08-27 17:01:13 +08:00
    @tabris17
    @DonaldY
    怪我前提没说清楚,我想的都是要判断状态,后续有很多业务逻辑,没有事务不好回滚,默认必须有事务的。谢谢大家,就到这把
    Aresxue
        18
    Aresxue  
       2019-08-27 17:35:54 +08:00   ❤️ 1
    乐观锁其实不是常规意义上的锁,在编程语言中一般通过 CAS 机制去实现,在 mysql 中比较有名的是 MVCC,需要使用乐观锁的场景一般是读多写少的情况,不然一直自旋可能效果还不如悲观锁。
    PS:MVCC 其实只能保证读的一致性,mysql 保证写一致性其实最后还是靠的 next-key
    haon
        19
    haon  
       2019-08-27 18:47:05 +08:00
    乐观锁没有加锁过程, 用户态即可完成, 加锁需要切换到内核态, 很慢
    glogo
        20
    glogo  
       2019-08-27 20:26:23 +08:00   ❤️ 1
    这其实很简单:
    悲观锁——悲观地假设交织执行的事务之间会有冲突发生,那么一开始就先限制事务能拿到的锁,只有事务执行完释放了锁,另一个事务才能执行;否则,spin or fail.
    乐观锁——乐观的假设交织执行的事务之间没有冲突发生,那么一开始就不限制事务的执行,等到事务要将更改写入磁盘(即 critial section 竞争区)时,才去判断这个事务能不能完成写入操作并释放锁;如果可以成功写入,那么就顺利退出,否则,事务执行失败 or spin for a while until succeed.

    所以,为什么乐观锁比悲观锁性能更好呢?答案是,it depends,根据使用场景而定。
    xalilo
        21
    xalilo  
    OP
       2019-08-28 09:27:50 +08:00
    @glogo 如果有选择答案的那种,我要选你做全场最佳😄😄😄
    glogo
        22
    glogo  
       2019-08-28 22:51:19 +08:00
    @xalilo Thanks
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   实用小工具   ·   980 人在线   最高记录 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 25ms · UTC 21:08 · PVG 05:08 · LAX 13:08 · JFK 16:08
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.