为啥这是一个死锁(MySQL 使用 InnoDB)

Posted

技术标签:

【中文标题】为啥这是一个死锁(MySQL 使用 InnoDB)【英文标题】:Why is this a deadlock (MySQL using InnoDB)为什么这是一个死锁(MySQL 使用 InnoDB) 【发布时间】:2011-04-18 08:53:38 【问题描述】:

SHOW INNODB ENGINE STATUS 显示这个并称之为死锁:

最新检测到的死锁

100923 22:29:21 * (1) 交易: 事务 0 5335752,活动 0 秒,操作系统线程 id 7992 插入 mysql 表正在使用 1,锁定 1 LOCK WAIT 5 锁结构,堆大小 1024,4 行锁,撤消日志条目 3 MySQL 线程 id 26,查询 id 14422 localhost 127.0.0.1 根更新 插入 history_messagearguments (history_id, messageArguments_ORDER, messageArguments) 值 (69, 1, '1') * (1) 等待授予此锁定: RECORD LOCKS space id 0 page no 179145 n bits 304 index fk_history_msgargs of table zvs_rkl_01_test.history_messagearguments trx id 0 5335752 lock_mode X在rec插入意图等待之前锁定间隙 记录锁,堆号 198 物理记录:n_fields 2;紧凑的格式;信息位 0 0:长度 8;十六进制 8000000000000048;升 H;; 1:长度 6;十六进制 0000006fe7c5; asc o ;;

* (2) 交易: 事务 0 5335748,活动 0 秒,操作系统线程 id 6988 插入,线程在 InnoDB 500 内声明 mysql 表正在使用 1,锁定 1 5 个锁结构,堆大小 1024,3 行锁,撤消日志条目 2 MySQL 线程 id 25,查询 id 14424 localhost 127.0.0.1 根更新 插入 history_messagearguments (history_id, messageArguments_ORDER, messageArguments) 值 (71, 0, '0') * (2) 持有锁: RECORD LOCKS 空间 id 0 页号 179145 n 位 304 索引 fk_history_msgargszvs_rkl_01_test.history_messagearguments trx id 0 5335748 lock_mode X 在记录之前锁定间隙 记录锁,堆号 198 物理记录:n_fields 2;紧凑的格式;信息位 0 0:长度 8;十六进制 8000000000000048;升 H;; 1:长度 6;十六进制 0000006fe7c5; asc o ;;

* (2) 等待此锁定被授予: RECORD LOCKS space id 0 page no 179145 n bits 304 index fk_history_msgargs of table zvs_rkl_01_test.history_messagearguments trx id 0 5335748 lock_mode X在rec插入意图等待之前锁定间隙 记录锁,堆号 198 物理记录:n_fields 2;紧凑的格式;信息位 0 0:长度 8;十六进制 8000000000000048;升 H;; 1:长度 6;十六进制 0000006fe7c5; asc o ;;

* 我们回滚交易 (2)

我不明白为什么这是一个死锁。事务 1 没有“WAITING FOR THIS LOCK TO BE GRANTED:”行。如果事务 1 没有持有任何锁,它就不能阻塞任何人,因此它不能成为死锁的一部分。

从理论上讲,我看不到这里写的条件 4 被满足: http://en.wikipedia.org/wiki/Deadlock#Necessary_conditions

在我看来,mysql 应该让事务 2 继续。完成后,事务 1 可以继续进行。

在这里 (http://***.com/questions/1851528/mysql-deadlock-explanation-needed) BrainCore 写道:

事务 2 “卡”在事务 1 的请求后面,一个 FIFO 队列。

谁能指出我的 MySQL 文档来确认这一点?我很难相信交易是严格按照它们到达的顺序执行的。

在有关表布局、隔离级别等的所有问题出现之前:我现在不寻求解决死锁的帮助。请问如何读取SHOW ENGINE STATUS OUTPUT。

【问题讨论】:

【参考方案1】:

读取事务 1 和 2: 从头到尾阅读:

什么类型以及为什么:lock_mode X 在记录插入意图等待之前锁定间隙 什么被阻止:记录锁空间 id 0 页号 179145 n 位 304 索引 fk_history_msgargs 表 zvs_rkl_01_test.history_messagearguments trx id 0 5335748 等待授予此锁定权限

InnoDB 存在并发写入问题,尤其是当您在 innodb 表的末尾插入数据时。

【讨论】:

如果插入在表的末尾,您能否引用 InnoDB 并发写入问题的说法?尝试对此主题进行更多研究,但很难找到信息。 这篇文章提供了一些额外的证据***.com/questions/50730278/…。

以上是关于为啥这是一个死锁(MySQL 使用 InnoDB)的主要内容,如果未能解决你的问题,请参考以下文章

mysql 发生死锁问题请求帮助

MySQL(InnoDB)是如何处理死锁的

巧用MySQL InnoDB引擎锁机制解决死锁问题(转)

详解MySQL(InnoDB)是如何处理死锁的

mysql insert into select 语句为啥会造成死锁

超赞,InnoDB调试死锁的方法!