MySQL 8.0 リファレンスマニュアル


15.7.5.1 InnoDB デッドロックの例

次の例は、ロックリクエストによってデッドロックが発生したときに、どのようにエラーが発生するのかを示しています。 この例には、A と B の 2 つのクライアントが登場します。

最初に、クライアント A が行を 1 つ含むテーブルを作成し、トランザクションを開始します。 トランザクション内で、A は共有モードで選択した行で S ロックを取得します。

mysql> CREATE TABLE t (i INT) ENGINE = InnoDB;
Query OK, 0 rows affected (1.07 sec)

mysql> INSERT INTO t (i) VALUES(1);
Query OK, 1 row affected (0.09 sec)

mysql> START TRANSACTION;
Query OK, 0 rows affected (0.00 sec)

mysql> SELECT * FROM t WHERE i = 1 FOR SHARE;
+------+
| i    |
+------+
|    1 |
+------+

次に、クライアント B がトランザクションを開始し、テーブルから行を削除しようとします。

mysql> START TRANSACTION;
Query OK, 0 rows affected (0.00 sec)

mysql> DELETE FROM t WHERE i = 1;

削除操作を行うには、X ロックが必要です。 クライアント A が保持している S ロックとの互換性がないために、ロックを付与できません。そのため、リクエストはその行のロックリクエストのキューに入れられ、クライアント B はブロックされます。

最後に、クライアント A もテーブルから行を削除しようとします。

mysql> DELETE FROM t WHERE i = 1;
ERROR 1213 (40001): Deadlock found when trying to get lock;
try restarting transaction

クライアント A は行を削除するために X ロックが必要であるため、ここでデッドロックが発生します。 ただし、クライアント B はすでに X ロックに対するリクエストを持っていて、クライアント A がその S ロックを解放するまで待機しているため、そのロックリクエストを付与することはできません。 B による X ロックに対する以前のリクエストが原因で、A が保持している S ロックを X ロックにアップグレードすることもできません。 その結果、InnoDB はクライアントのいずれかに対してエラーを生成し、そのロックを解放します。 クライアントは、次のエラーを返します。

ERROR 1213 (40001): Deadlock found when trying to get lock;
try restarting transaction

この時点で、ほかのクライアントに対するロックリクエストを付与できるようになり、テーブルから行が削除されます。


関連キーワード:  InnoDB, テーブル, ロック, 構成, 圧縮, スペース, トランザクション, インデックス, INFORMATION, SCHEMA