试图理解InnoDB表上的MySQL死锁

试图理解InnoDB表上的MySQL死锁,mysql,transactions,innodb,database-deadlocks,Mysql,Transactions,Innodb,Database Deadlocks,我试图理解MySQL在并发客户机处理相同表时发现的死锁。这是“SHOW InnoDB STATUS”命令的有趣部分: 我从这个日志中了解到,事务(1)正在等待获取表testsuiteINode的索引INodeparent\u basename上的共享锁。现在,事务(2)在这个索引上有一个排他锁。但奇怪的是,事务(2)也在等待给定表上的X锁。为什么呢?如果事务(2)已经有锁,为什么要等待它 (一般来说,我还没有找到任何文档确切地解释如何读取status命令的输出-如果有人也能向我指出这一点,那将是

我试图理解MySQL在并发客户机处理相同表时发现的死锁。这是“SHOW InnoDB STATUS”命令的有趣部分:

我从这个日志中了解到,事务(1)正在等待获取表
testsuite
INode
的索引
INodeparent\u basename
上的共享锁。现在,事务(2)在这个索引上有一个排他锁。但奇怪的是,事务(2)也在等待给定表上的X锁。为什么呢?如果事务(2)已经有锁,为什么要等待它


(一般来说,我还没有找到任何文档确切地解释如何读取status命令的输出-如果有人也能向我指出这一点,那将是很有趣的)

在这种情况下,事务2获得了前一条语句的共享锁。(*(2)持有锁:)

然后,事务1尝试获取同一行上的独占锁,并等待删除共享锁


然后,事务2在另一条语句中试图获取同一行上的独占锁。死锁发生了。

< p>我不知道它是否会帮助,但要考虑的是导致锁定的操作序列。在应用程序的一个位置,您似乎正在创建锁,例如

表1 表2

在另一方面

表2 表1(仅为示例)

在看不到实际代码的情况下,我建议研究类似这样的事情,并确保以相同的顺序处理/更新/插入记录,以便它们都像这样工作

从表1插入/更新 然后插入/更新表2

这样,总是先在表1上尝试第一次锁定。。如果不能,那么在表1发布之前,它甚至不会尝试表2


然后,对表2应用任何更改并完成事务。当表2和表1都发布后,下一个等待表1发布的事务就可以继续进行。

您找到答案了吗?我也有同样的问题。不,我找不到这个问题的答案。在我花了几个小时试图理解它之后,我只需要以不同的方式编写流程代码,并以编程方式序列化对数据库的部分访问,以避免MySQL发现的任何可能的死锁情况。性能方面可能更差,但我没有任何其他可能性。关于如何翻译status命令输出,您(或任何其他需要帮助的人)可能希望查看此博客,我发现没有,(2)已持有独占锁。(1) 正在尝试获得一个共享锁。
------------------------
LATEST DETECTED DEADLOCK
------------------------
120704 16:17:51
*** (1) TRANSACTION:
TRANSACTION 0 3547576, ACTIVE 0 sec, process no 10886, OS thread id 140547111458560 inserting
mysql tables in use 1, locked 1
LOCK WAIT 2 lock struct(s), heap size 368, 1 row lock(s), undo log entries 1
MySQL thread id 41941, query id 1725666 localhost testsuite update
insert into `INode` (`status`,`_type`,`group`,`ctime`,`parent`,`shared`,`basename`,`_rowid`,`displayname`,`user`,`content_type`,`mtime`,`position`,`atime`,`size`) values ('Published','Group','12','2012-07-04 16:17:48.996869','2',null,'1','12','1','3','application/x-empty','2012-07-04 16:17:48.996896','1','2012-07-04 16:17:48.996914',null)
*** (1) WAITING FOR THIS LOCK TO BE GRANTED:
RECORD LOCKS space id 0 page no 5554 n bits 80 index `INodeparent_basename` of table `testsuite`.`INode` trx id 0 3547576 lock mode S waiting
Record lock, heap no 12 PHYSICAL RECORD: n_fields 3; compact format; info bits 32
 0: len 4; hex 80000002; asc     ;; 1: len 1; hex 31; asc 1;; 2: len 4; hex 8000000b; asc     ;;

*** (2) TRANSACTION:
TRANSACTION 0 3547575, ACTIVE 0 sec, process no 10886, OS thread id 140547107845888 inserting, thread declared inside InnoDB 493
mysql tables in use 1, locked 1
13 lock struct(s), heap size 3024, 17 row lock(s), undo log entries 21
MySQL thread id 41940, query id 1725808 localhost testsuite update
replace into `INode` (`status`,`_type`,`position`,`group`,`ctime`,`parent`,`basename`,`_rowid`,`displayname`,`user`,`content_type`,`mtime`,`shared`,`atime`,`size`) values ('Published','Group','0','2','2012-07-04 16:17:49','1','groups','2','admin','3','application/x-empty','2012-07-04 16:17:49',null,'2012-07-04 16:17:49',null),('Published','Group','1','11','2012-07-04 16:17:51.064074','2','1','11','1','3','inode/directory','2012-07-04 16:17:51.064074',null,'2012-07-04 16:17:51.064074',null)
*** (2) HOLDS THE LOCK(S):
RECORD LOCKS space id 0 page no 5554 n bits 80 index `INodeparent_basename` of table `testsuite`.`INode` trx id 0 3547575 lock_mode X locks rec but not gap
Record lock, heap no 3 PHYSICAL RECORD: n_fields 3; compact format; info bits 0
 0: len 4; hex 80000001; asc     ;; 1: len 6; hex 67726f757073; asc groups;; 2: len 4; hex 80000002; asc     ;;

Record lock, heap no 12 PHYSICAL RECORD: n_fields 3; compact format; info bits 32
 0: len 4; hex 80000002; asc     ;; 1: len 1; hex 31; asc 1;; 2: len 4; hex 8000000b; asc     ;;

*** (2) WAITING FOR THIS LOCK TO BE GRANTED:
RECORD LOCKS space id 0 page no 5554 n bits 80 index `INodeparent_basename` of table `testsuite`.`INode` trx id 0 3547575 lock_mode X waiting
Record lock, heap no 12 PHYSICAL RECORD: n_fields 3; compact format; info bits 32
 0: len 4; hex 80000002; asc     ;; 1: len 1; hex 31; asc 1;; 2: len 4; hex 8000000b; asc     ;;

*** WE ROLL BACK TRANSACTION (1)