如何处理MySQL死锁问题
MySQL中的锁兼容性列表一般都有这种关系。如果你第一次读,你会有点困惑,感觉抓不住重点。其实还有一个小技巧。
首先,InnoDB实现了两种类似的行锁,即S(共享锁)和Lock),意向锁是相互兼容的,这句话很重要,根据一半的内容就清楚了对这个想法。另一部分是S和X兼容性。 S锁和X锁的组合是互斥的,除了一种情况例外,即它们都是S锁并且是兼容的。所以按照这个思路,这张图基本不用背就能看懂。
看来S锁的组合很软。从这个场景来看,如果保持兼容的话,死锁的概率应该很低。事实上,在 RR 和 RC 隔离级别下,我们可以逐渐展开并举一反三。
如果两个会话中S锁的组合是互兼容的,那么后续的X锁的组合是互斥的。
那么在两个并发会话的场景下,死锁步骤如下:
mysql> create table dt1(id int unique
查询正常,0 行受影响(0.03 秒)
会话 1:
开始;
在共享模式下选择 *from dt1 锁;--显式共享锁
会话2:
begin;
select *from dt1 lock in share mode; --显式共享锁
会话1:
insert into dt1values(1); --阻塞
会话2:
insert into dt1values(2); --触发死锁
所以上面语句的特点就很明显了,插入的数据是1和 2 分别。看来互补冲突是不可能的。
我们的进度稍微快一点,我们可能很少看到直接声明share模式,但是经常是其他场景触发的。主要原因之一是检查重复数据会打开S锁。这是一个比较特殊的点,需要注意。
按照这个来扩展,可以轻松扩展到3个会话。
会话1只负责插入一条数据,会话2和3也插入一条记录(会话2和3自动提交)。不过由于唯一索引检查的原因,会话2和会话3都会被I开启S锁,由于是兼容的,所以暂时没有影响。如果session 1正常提交,session 2和session 3的检查就会生效,导致数据没有插入,违反了唯一性约束。但是,如果我们反其道而行之,我们可以使用回滚来释放锁,然后sessions 2和3会成功获取S锁,立即获取X锁。具体算法就不讨论了。此时,它们互相阻塞,导致会话3出现死锁,但是会话2的数据插入仍然会成功。
会话 1:
开始;
插入 dt1 值(1);
会话 2:
插入 dt1 值(1);
会话 3:
插入 dt1 值(1);
会话 1:
rollback;
看起来是一个很微妙的小测试,但是却包含了这个大道理。比如按照这个思路,如果下面两条语句都是delete,也会触发死锁。有时我们可以直接使用图例或者通过死锁日志进行推理。我的灵感之一是太极拳。
从锁的角度来理解会好很多。
用一张不太形象的图,左边是会话1中的插入操作,右边是会话2和会话3中的插入操作,都持有S锁,那么就会有同样的原因。原因是事务回滚后,他们的S锁会升级为X锁,导致死锁发生。
按照这个思路,我们可以继续拓展几个场景。例如删除方法。
按照这个思路,可以构造出很多死锁场景。
以上就是《如何处理MySQL死锁问题》文章的全部内容,感谢您的阅读!相信大家都有一定的了解,希望分享的内容对大家有所帮助。如果您想了解更多知识,请关注行业资讯频道!
2. 本站积分货币获取途径以及用途的解读,想在本站混的好,请务必认真阅读!
3. 本站强烈打击盗版/破解等有损他人权益和违法作为,请各位会员支持正版!
4. 编程技术 > 如何处理MySQL死锁问题