记一次神奇的MySQL死锁排查
这段代码的意思是生涯一个设置文件,,假如产生了独一索引斗嘴那么就会举办更新,虽然这里也许写得不是很类型,着实可以用
也可以到达同样的结果,可是就算用这个着实也会发存亡锁。看了代码之后同事又给我发了其时营业日记, 可以望见这里有三条同时产生的日记,声名都产生了独一索引斗嘴进入了更新的语句,然后产生的死锁。到这里谜底终于轻微有点端倪了。 这个时辰再看我们的表布局如下(做了简化处理赏罚):
我们的tenant_id是用来做独一索引,我们的插入和更新的where前提都是基于独一索引来操纵的。
到了这里感受插入的时辰对独一索引加锁有相关,接下来我们举办下一步的深入分解。 深入分解 上面我们说有三个事宜进入update语句,为了简化声名这里我们只必要两个事宜同时进入update语句即可,下面的表格展示了我们整个的产生进程: 小提醒:S锁是共享锁,X锁是互斥锁。一样平常来说X锁和S,X锁都互斥,S锁和S锁不互斥。 我们从上面的流程中望见产生这个死锁的要害必要获取S锁,为什么我们再插入的时辰必要获取S锁呢?由于我们必要检测独一索引?在RR断绝级别下假如要读取那么就是当前读,那么着实就必要加上S锁。这里发明独一键已经存在,这个时辰执行update就会被两个事宜的S锁相互阻塞,从而形成上面的轮回守候前提。 小提醒: 在MVCC中,当前读和快照读的区别:当前读每次必要加锁(可以使共享锁可能互斥锁)获取到最新的数据,而快照读是读取的是这个事宜开始的时辰谁人快照,这个是通过undo log去举办实现的。 这个就是整个死锁的缘故起因,能呈现这种死锁的尚有一个环境,就是统一时刻来三个插入操纵,个中先插入的谁人事宜假如最后回滚了,别的两个事宜也会呈现这种死锁。 办理方案 这里的焦点题目是必要把S锁给干掉,这里有三个可供参考的办理方案:
第一种要领不太实际,事实断绝级别不能等闲的修改。第三种要领又较量贫困。以是第二种要领是我们最后确定的。 总结 说了这么多,最后做一个小小的总结吧。排查死锁这种题目的时辰偶然辰光看死锁日记偶然辰会办理不了题目,必要团结整个的营业日记,代码以及表布局来举办说明,才气获得正确的功效。虽然上面有一些数据库锁的根基常识假如不相识可以查察我的另一篇文章为什么开拓职员必要相识数据库锁。 最后这篇文章被我收录于JGrowing-CaseStudy篇,一个全面,优越,由社区一路共建的Java进修蹊径,假如您想参加开源项目标维护,可以一路共建,github地点为:https://github.com/javagrowing/JGrowing 贫困给个小星星哟。 (编辑:湖南网) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |