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 没有生效时,死锁就已经产生也是经常发生的事情。

所以我们要梳理好业务流程,以及业务影响的数据范围。缩小死锁产生概率。不然很有可能面临人工处理死锁的场景。