11

我试图了解 MySQL 在同一表上的并发客户端处理期间发现的死锁。这是“SHOW InnoDB STATUS”命令的有趣部分:

------------------------
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)

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

(总的来说,我还没有找到任何文档可以准确解释如何读取状态命令的输出 - 如果有人也可以向我指出这一点,那将会很有趣)

4

2 回答 2

1

In this case, transaction 2 acquired a shared lock for a previous statement.(* (2) HOLDS THE LOCK(S):)

Then, transaction 1 attempted to acquire an exclusive lock on the same row, and is waiting for the shared lock to be removed.

Then, transaction 2, in another statement, attempted to acquire an exclusive lock on the same row. Deadlock occured.

于 2012-07-12T04:57:41.840 回答
-1

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

表 1 表 2

在另一个做

表 2 表 1(仅举例)

在没有看到实际代码的情况下,我建议您研究这样的事情并确保您以相同的工作/更新/插入记录顺序执行它们,以便它们都可以像这样工作

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

这样,第一个锁总是首先尝试在表 1 上。如果不能成功,那么它甚至不会尝试表 2,直到表 1 被释放。

然后,对表 2 应用任何更改并完成您的事务。当表 2 和表 1 都被释放时,表 1 上等待释放的下一个事务可以继续进行。

于 2013-04-06T11:53:34.553 回答