MySQL 强事务处理for update 死锁案例

2018-10-2321:41:34数据库教程Comments2,918 views字数 769阅读模式
很多强事务的场景中,我们经常用到for update进行显示锁定来确保数据的一致性,但是经过线上发现,有一种场景必出现死锁,下面简单描述一下,
CREATE TABLE `dbcache` (`id` int(10) unsigned NOT NULL AUTO_INCREMENT,文章源自菜鸟学院-https://www.cainiaoxueyuan.com/sjk/7134.html

`skey` varchar(32) NOT NULL,文章源自菜鸟学院-https://www.cainiaoxueyuan.com/sjk/7134.html

`value1` varchar(100) NOT NULL,文章源自菜鸟学院-https://www.cainiaoxueyuan.com/sjk/7134.html

PRIMARY KEY (`id`)文章源自菜鸟学院-https://www.cainiaoxueyuan.com/sjk/7134.html

) ENGINE=InnoDB文章源自菜鸟学院-https://www.cainiaoxueyuan.com/sjk/7134.html

注:默认隔离级别为“REPEATABLE-READ”文章源自菜鸟学院-https://www.cainiaoxueyuan.com/sjk/7134.html

session 1:MySQL 强事务处理for update 死锁案例文章源自菜鸟学院-https://www.cainiaoxueyuan.com/sjk/7134.html

session 2:MySQL 强事务处理for update 死锁案例文章源自菜鸟学院-https://www.cainiaoxueyuan.com/sjk/7134.html

(红色数字为测试执行的流程)
第一步:session 1 ,for update开启是一个锁定,但是id=4 没有数据,这个时候获取了gap lock;
第二步:session 2 ,for update 开启一个锁定,id=4 也没有数据,这个时候,也需要获取gap lock,按照常规来说,他是需要等待第一步的gap lock释放才能添加上锁定的,但是mysql这个时候确让session 2也获得了gap lock,也就是说两个gap lock 的x锁竟然兼容了;
第三步:等到session 2释放 gap lock;
第四步:等待session 1释放gap lock,然后就完美死锁
按照以上步骤100%复现死锁问题,涉及到mysql的所有版本,咨询了官方一同学,说innodb就是这么设计了,目前暂时无法修复这个问题;
大家肯定会问,为毛线要for update一个不存在的值,其实真实场景为:id如果存在,就更新,如果不存在,就写入,但是在并发场景下,就触发了一个目前无解的X锁兼容问题;所以大家在真实涉及事务项目中,一定要测试测试在测试,否则结果可能会颠覆自己所了解的一些知识;由于我们该业务的访问量不大,后把语句直接改为replace into,该问题绕开;
文章源自菜鸟学院-https://www.cainiaoxueyuan.com/sjk/7134.html
  • 本站内容整理自互联网,仅提供信息存储空间服务,以方便学习之用。如对文章、图片、字体等版权有疑问,请在下方留言,管理员看到后,将第一时间进行处理。
  • 转载请务必保留本文链接:https://www.cainiaoxueyuan.com/sjk/7134.html

Comment

匿名网友 填写信息

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定