我读过关于InnoDB锁的mysql参考手册。我得到了:(出发地:http://dev.mysql.com/doc/refman/5.5/en/innodb-locks-set.html)
INSERT设置插入行的独占锁。此锁是索引记录锁,而不是下一个键锁(即没有间隙锁),也不会阻止其他会话插入插入行之前的间隙。
在插入行之前,设置称为插入意图间隙锁的间隙锁类型。此锁指示要以这样的方式插入多个事务,即插入到同一索引间隙中的多个事务不需要等待对方,如果它们不在间隙内的相同位置插入。假设有值为4和7的索引记录。在获得插入行的独占锁之前,尝试插入值为5和6的单独事务在获得插入行的排他锁之前,分别将4和7之间的间隔锁定为insert意图锁,但不要彼此阻塞,因为行是不冲突的。
如果发生重复键错误,则在重复索引记录上设置共享锁.如果有多个会话试图插入同一行(如果另一个会话已经具有独占锁),则共享锁的这种使用会导致死锁。如果另一个会话删除行,则可能发生这种情况。假设InnoDB表t1具有以下结构:
创建表t1 ( INT,主键(i)) ENGINE = InnoDB;现在假设三个会话按照顺序执行以下操作:
第1场会议:
START TRANSACTION;
INSERT INTO t1 VALUES(1);
第2场会议:
START TRANSACTION;
INSERT INTO t1 VALUES(1);
第3场会议:
START TRANSACTION;
INSERT INTO t1 VALUES(1);
第1场会议:
ROLLBACK;
会话1的第一个操作获取行的独占锁。会话2和会话3的操作都会导致重复键错误,并且它们都会请求行的共享锁。当会话1回滚时,它会释放该行上的独占锁,并授予会话2和3的排队共享锁请求。此时,会话2和3死锁:由于对方持有的共享锁,这两个会话都不能为该行获取排他锁。
我做了一个实验,我发现这是事实。
我的问题是:
(1)我发现,如果提交会话1,则不会发生死锁。为什么?当我提交会话1时,X行锁也将被释放。所以我不明白。
谢谢。
发布于 2016-08-26 02:48:57
我怀疑这是一种边缘情况,不值得提高效率。请注意,您必须得到三个会话试图抓取同一行-一个罕见的发生。你做了回滚--也是很少见的。因此,所发生的死锁是过份的,但不值得修正。因此,人们必须准备好在任何地方处理死锁。
FYI,如果这是Galera集群的3个节点,那么COMMIT
上就会出现代码必须处理的错误。如果对多个节点多次应用此事务(使用回滚或提交),我怀疑会发生更多奇怪的事情。
现在请回答你的问题..。据推测,死锁不会发生,因为其中一个线程获得了独占锁,而另一个线程被“等待”而不是“死锁”击中。
https://stackoverflow.com/questions/39156969
复制相似问题