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 のインデックスで共有ロックを取得するのを待っているということtestsuiteです。INode. 現在、トランザクション (2) は、この同じインデックスに対して排他ロックを持っています。しかし奇妙なのは、トランザクション (2) も指定されたテーブルに対する X ロックを待機していることです。何故ですか?トランザクション (2) が既にロックを取得している場合、なぜそれを待つのでしょうか?

(一般に、status コマンドの出力を読み取る方法を正確に説明しているドキュメントは見つかりませんでした。誰かがそれを指摘してくれたら興味深いでしょう)

4

2 に答える 2

1

この場合、トランザクション 2 は前のステートメントの共有ロックを取得しました。( * (2) HOLDS THE LOCK(S):)

次に、トランザクション 1 は同じ行で排他ロックを取得しようとし、共有ロックが削除されるのを待機しています。

次に、別のステートメントで、トランザクション 2 が同じ行の排他ロックを取得しようとしました。デッドロックが発生しました。

于 2012-07-12T04:57:41.840 に答える
-1

それが役立つかどうかはわかりませんが、考慮すべきことの 1 つは、ロックを引き起こす一連の操作です。アプリのある場所で、次のようなロックを作成しているようです

表 1 表 2

そして別のことで

表 2 表 1 (一例)

実際のコードを見ずに、このようなことを調べて、レコードの作業/更新/挿入の同じ順序でそれらを実行して、すべてが次のように機能するようにすることをお勧めします

テーブル 1 からの挿入/更新、次にテーブル 2 の挿入/更新

このように、最初のロックは常に最初にテーブル 1 で試行されます。それができない場合は、テーブル 1 が解放されるまでテーブル 2 を試行しません。

次に、テーブル 2 に変更を適用し、トランザクションを終了します。その後、テーブル 2 と 1 の両方が解放されると、テーブル 1 で解放を待っている次のトランザクションを続行できます。

于 2013-04-06T11:53:34.553 に答える