QA@IT
«質問へ戻る

質問を投稿

MySQL (InnoDB) でデッドロック検知される条件について

InnoDBにはデッドロック検出機能があると言われていますが、これがいまひとつどういう条件で発動するのかがよくわかっていません。

http://dev.mysql.com/doc/refman/5.5/en/innodb-deadlock-detection.html

とくに、SHOW ENGINE INNODB STATUSLATEST DETECTED DEADLOCKセクションをみたときに、transaction (1), (2)ともにACTIVE 0 secで、まったく待ち時間なく、瞬時にデッドロックと判定されていることがあります。

この、デッドロックと判定される条件とは、具体的にどういうものでしょうか?

具体例を出します。今回発生してる例では、同じUNIQUE INDEX (a, b, c)上の全く同一のタプル(1, 2, 3)に対して

SELECT ... WHERE a=1 and b=2 and c=3 FOR UPDATE

INSERT INTO ... (a, b, c, v) VALUES (1,2,3,1) ON DUPLICATE KEY UPDATE v = v + 1

がコンフリクトして、前者がロールバックされています。コード的には、単純化していうと

START TRANSACTION
SELECT ... WHERE a=1 and b=2 and c=3 FOR UPDATE
INSERT INTO ... (a, b, c, v) VALUES (1,2,3,1) ON DUPLICATE KEY UPDATE v = v + 1
COMMIT

が並列に走るイメージです。

期待した挙動は、SELECT ... FOR UPDATEに入った時点で、すでに稼働中のINSERT ... ON DUPLICATE KEY UPDATEが同じタプルに対して存在していたら、それが終わるまで(ロックの解放を)待つ、というものでしたが、そのようには動いてくれず、デッドロックになってしまうようです。

InnoDBにはデッドロック検出機能があると言われていますが、これがいまひとつどういう条件で発動するのかがよくわかっていません。

http://dev.mysql.com/doc/refman/5.5/en/innodb-deadlock-detection.html

とくに、`SHOW ENGINE INNODB STATUS`の`LATEST DETECTED DEADLOCK`セクションをみたときに、transaction (1), (2)ともにACTIVE 0 secで、まったく待ち時間なく、瞬時にデッドロックと判定されていることがあります。

この、デッドロックと判定される条件とは、具体的にどういうものでしょうか?

具体例を出します。今回発生してる例では、同じUNIQUE INDEX (a, b, c)上の全く同一のタプル(1, 2, 3)に対して

```
SELECT ... WHERE a=1 and b=2 and c=3 FOR UPDATE
```

と

```
INSERT INTO ... (a, b, c, v) VALUES (1,2,3,1) ON DUPLICATE KEY UPDATE v = v + 1
```

がコンフリクトして、前者がロールバックされています。コード的には、単純化していうと

```
START TRANSACTION
SELECT ... WHERE a=1 and b=2 and c=3 FOR UPDATE
INSERT INTO ... (a, b, c, v) VALUES (1,2,3,1) ON DUPLICATE KEY UPDATE v = v + 1
COMMIT
```

が並列に走るイメージです。

期待した挙動は、`SELECT ... FOR UPDATE`に入った時点で、すでに稼働中の`INSERT ... ON DUPLICATE KEY UPDATE`が同じタプルに対して存在していたら、それが終わるまで(ロックの解放を)待つ、というものでしたが、そのようには動いてくれず、デッドロックになってしまうようです。