• 【三大锁】悲观锁——mysql悲观锁


    一 三大常用锁

    • 悲观锁
      •   你准备去银行取10w了,跟银行提前打个招呼,有个10w现金谁都别动。(一般只限制写-别人不能取那10w但是能查到银行总体余额,某些场景会限制读)
    • 乐观锁
      •   你准备取10w了,不打招呼,撸起袖子(开始事物,准备好回滚),直接去银行,到了之后,银行告诉你10w在那里,你正好取走(事物提交)。 也有可能去了后,银行说10w没了,那你不取了(事物回滚)
      •       这里面涉及到一个细节,你拿的10w可能是 路人甲 早上取走了最后10w,然后在你到达之前 路人乙 存了10w。 如果你的业务场景是必须要银行的新钱,而不是别人刚存的,那你可以问下银行这个钱是否有人动过(标记操作流水版本号,cas算法的特点)
    • 分布式锁
      •   饭店门口很多顾客(多个访问线程),但是餐桌资源只有空闲的时候才会让人进去。有客户取消或者用餐完毕,某个4人桌就空闲出来了,你就可以去抢占这个4人桌的号(分布式锁),先来先得!(和排号系统还是有点不一样的)

    二 实现方式

    • 分布式锁
      •   基本都是拿悲观锁(如 redis: setnx+看门狗+unique_value)
    • 乐观锁
      •   redis的watch
      •       mysql的step1: select step2: update .set. where id = pre_id and version = pre_version 然后判断result是否>0
      •       cas算法基本原理类似,需考虑version
    • 悲观锁
      • reids的setnx + 看门狗
      • 不限制消息发送频率只限制重复发送的场景,可以带上msgid作为setnx的value
      • 怕del错lock,可以把uniq_id 作为setnx的value,然后del之前,get判断uniq_id是否一致! get和del可以通过lua制作成原子命令!
      • mysql的select for update (本文重点)

     

    三 mysql悲观锁

    用户x下单,系统查询是否有存货,生成订单balabala ( 我们称为process ),存货-1
    process的过程中,可能用户y 就下单了,或者比你下单早的用户z 刚好结算到存货-1了,那用户x 直接把库存降到-1了。 虽然可能有数据库unsigned等保护,那如果库存设置的是底货必须是10以上呢?

     所以我们要用到select ..  for update

    这玩意就是把select 直接锁住,不让别人增删改(查允许)

    如果命中了索引,含主键索引、唯一索引,那么是行锁;否则是表锁;

     cmd1 不commit

    cmd2 会阻塞

    然后cmd1 commit;则cmd2 success

     如果cmd2要update等操作,会命中cmd1的查询结果行(只要包含cmd1的结果,你想想,别人锁住了,你却要动他,虽然你要动1w行,只有其中一行是cmd1的结果,但是就是卡住了,没办法!), 则会阻塞,时间久了会down;未命中cmd1的查询结果行,则没有任何影响。 

    cmd1如果resulet为空,那么根据上条结论,也能知道,相当于没锁。

    因为name是非索引,这时候直接锁表了,虽然和cmd1的result无关,还是卡住了! 

  • 相关阅读:
    【数据结构】| 并查集及其优化实现
    nginx 集群部署
    SQL映射XML文件
    outsystems合集系列(三)
    Python数据特征分析1-分布分析(极差,频率直方图等)
    AlCl -氯铝酸离子液体|FeCl -氯铁酸离子液体|ZnCl-氯锌酸离子液体金属络合系列离子液体
    Spring底层原理学习笔记--第四讲--(常见bean后处理器与@Autowired bean后处理器执行分析)
    工业互联网网络体系安全防护研究
    LeetCode刷题系列 -- 78. 子集
    [Spring Framework]注解开发③(依赖注入)
  • 原文地址:https://blog.csdn.net/bushuwei/article/details/126429250