MySQL 事物死锁解析
在使用mysql数据库中,随着我们业务与功能模块的增加、数据库的事物数量会随之上升。在开发业务功能的场景中我们会经常开启事物操作数据,或者开启分布式全局事物操作数据时、事物过多,在并发进行的场景中往往会有几率产生事物死锁问题。
那么我们来分析一下事物死锁产生的原因:
两个 session 连接:一个session持有T1事物,另外一个session持有T2事物。
1.T1事物修改rows1
2.T2事物修改rows2
3.T2事物修改rows1
4.T2等待T1释放rows1的x锁
5.T1事物修改Rows2
6.T1等待T2释放rows2的x锁
7.相互等待死锁
死锁在没有外力的干扰下,程序本身无力解决此问题。 必须借助人为或者另外的守护线程来解决此死锁问题。
解决死锁的方法也很简单:释放其中一个事物,让其回滚即可。
但回滚有一个问题,回滚哪个事物更合理,mysql采用的是根据undo log中谁的条数更多,谁的权重越大,则舍弃权重更小的事物进行回滚,可以更好解决事物死锁。让其回滚的数据量尽量减少,以减少服务的性能牺牲。
系统中任何一个事务发生死锁的概率≈n2r4/4R2
n:事务中事务的数量n,数量越多发生死锁的概率越大(事物包裹事物数量)
r:每个事务操作的数量r,每个事务操作的数量越大,发生死锁的概率越大(事物操作的行数)
R: 操作数据的集合R,越小发生死锁的概率越大(不同事物却操作到某集合一样的数据-数据集合,修改的数据越分散,数据集合越多,x锁发生在同一条数据的机率越小)
mysql的主动事物检测:wait-for graph
在每个session的事物开始前可以通过算法提前得知是否有事物回路(两个事物相互影响对方x锁数据而形成回路) ,提前释放其中undo log权重较小的事物。
但在复杂的业务场景中 mysql的主动事物检测wait-for graph 没有生效时,死锁就已经产生也是经常发生的事情。
所以我们要梳理好业务流程,以及业务影响的数据范围。缩小死锁产生概率。不然很有可能面临人工处理死锁的场景。