行き詰まり
DEADLOCKSテーブルには、現在の TiDB ノードで最近発生したいくつかのデッドロック エラーの情報が表示されます。
USE INFORMATION_SCHEMA;
DESC deadlocks;
出力は次のようになります。
+-------------------------+---------------------+------+------+---------+-------+
| Field                   | Type                | Null | Key  | Default | Extra |
+-------------------------+---------------------+------+------+---------+-------+
| DEADLOCK_ID             | bigint(21)          | NO   |      | NULL    |       |
| OCCUR_TIME              | timestamp(6)        | YES  |      | NULL    |       |
| RETRYABLE               | tinyint(1)          | NO   |      | NULL    |       |
| TRY_LOCK_TRX_ID         | bigint(21) unsigned | NO   |      | NULL    |       |
| CURRENT_SQL_DIGEST      | varchar(64)         | YES  |      | NULL    |       |
| CURRENT_SQL_DIGEST_TEXT | text                | YES  |      | NULL    |       |
| KEY                     | text                | YES  |      | NULL    |       |
| KEY_INFO                | text                | YES  |      | NULL    |       |
| TRX_HOLDING_LOCK        | bigint(21) unsigned | NO   |      | NULL    |       |
+-------------------------+---------------------+------+------+---------+-------+
DEADLOCKS表では、複数の行を使用して同じデッドロックイベントを表示し、各行にはデッドロックイベントに関係するトランザクションの1つに関する情報が表示されます。TiDBノードが複数のデッドロックエラーを記録した場合、各エラーはDEADLOCK_ID列を使用して区別されます。同じDEADLOCK_ID同じデッドロックイベントを示します。7 DEADLOCK_IDグローバルな一意性を保証するものではなく、永続化されないことに注意してください。同じ結果セット内の同じデッドロックイベントのみを示します。
DEADLOCKSテーブル内の各列フィールドの意味は次のとおりです。
- DEADLOCK_ID: デッドロックイベントのID。テーブル内に複数のデッドロックエラーが存在する場合、この列を使用して、異なるデッドロックエラーに属する行を区別できます。
- OCCUR_TIME: デッドロック エラーが発生した時刻。
- RETRYABLE: デッドロックエラーを再試行できるかどうか。再試行可能なデッドロックエラーの説明については、セクション再試行可能なデッドロックエラー参照してください。
- TRY_LOCK_TRX_ID: ロックを取得しようとするトランザクションのID。このIDはトランザクションの- start_tsでもあります。
- CURRENT_SQL_DIGEST: ロックを取得するトランザクションで現在実行されている SQL ステートメントのダイジェスト。
- CURRENT_SQL_DIGEST_TEXT: ロックを取得するトランザクションで現在実行されている SQL ステートメントの正規化された形式。
- KEY: トランザクションがロックしようとしたブロックされたキー。このフィールドの値は16進文字列で表示されます。
- KEY_INFO:- KEYの詳細情報。4- KEY_INFOセクションを参照してください。
- TRX_HOLDING_LOCK: 現在キーのロックを保持し、ブロックを引き起こしているトランザクションのID。このIDはトランザクションの- start_tsでもあります。
最近の 10 件のデッドロック イベントの情報がDEADLOCKSテーブルに記録されます。
KEY_INFO
KEY_INFO列目はKEY列目の詳細情報です。情報はJSON形式で表示されます。各フィールドの説明は以下の通りです。
- "db_id": キーが属するスキーマの ID。
- "db_name": キーが属するスキーマの名前。
- "table_id": キーが属するテーブルの ID。
- "table_name": キーが属するテーブルの名前。
- "partition_id": キーが配置されているパーティションの ID。
- "partition_name": キーが配置されているパーティションの名前。
- "handle_type": 行キー(つまり、データ行を格納するキー)のハンドルタイプ。可能な値は次のとおりです。- "int": ハンドル タイプは int です。つまり、ハンドルは行 ID です。
- "common": ハンドルの型が int64 ではありません。クラスター化インデックスが有効な場合、この型は非 int 型の主キーに表示されます。
- "unknown": ハンドル タイプは現在サポートされていません。
 
- "handle_value": ハンドル値。
- "index_id": インデックスキー(インデックスを格納するキー)が属するインデックス ID。
- "index_name": インデックス キーが属するインデックスの名前。
- "index_values": インデックス キー内のインデックス値。
上記のフィールドのうち、該当しない、または現在利用できない場合、そのフィールドはクエリ結果から省略されます。例えば、行キー情報にはindex_id 、 index_name 、 index_values含まれません。インデックスキーにはhandle_typeとhandle_value含まれません。非パーティションテーブルではpartition_idとpartition_name表示されません。削除されたテーブルのキー情報ではtable_name 、 db_id 、 db_name 、 index_nameなどのスキーマ情報を取得できず、テーブルがパーティションテーブルであるかどうかを区別できません。
注記:
パーティションが有効になっているテーブルからキーが取得され、クエリ中に何らかの理由(例えば、キーが属するテーブルが削除されているなど)により、キーが属するスキーマの情報が取得できない場合、キーが属するパーティションのIDが
table_idフィールドに表示されることがあります。これは、TiDBが複数の独立したテーブルのキーをエンコードするのと同じ方法で、異なるパーティションのキーをエンコードするためです。したがって、スキーマ情報が欠落している場合、TiDBはキーがパーティション化されていないテーブルに属しているのか、それともテーブル内の1つのパーティションに属しているのかを確認できません。
再試行可能なデッドロックエラー
注記:
このセクションはTiDB Cloudには適用されません。
トランザクションAがトランザクションBによって既に保持されているロックによってブロックされ、トランザクションBが現在のトランザクションAによって保持されているロックによって直接的または間接的にブロックされている場合、デッドロックエラーが発生します。このデッドロックには、以下の2つのケースが考えられます。
- ケース 1:トランザクションB は、トランザクション A の開始後、トランザクション A がブロックされる前に実行されたステートメントによって生成されたロックによって (直接的または間接的に) ブロックされる可能性があります。
- ケース 2:トランザクションB も、トランザクション A で現在実行中のステートメントによってブロックされる可能性があります。
ケース 1 では、TiDB はトランザクション A のクライアントにデッドロック エラーを報告し、トランザクションを終了します。
ケース2では、トランザクションAで現在実行中の文がTiDBで自動的に再試行されます。例えば、トランザクションAが以下の文を実行するとします。
UPDATE t SET v = v + 1 WHERE id = 1 OR id = 2;
トランザクションB は次の 2 つのステートメントを連続して実行します。
UPDATE t SET v = 4 WHERE id = 2;
UPDATE t SET v = 2 WHERE id = 1;
次に、トランザクション A がid = 1とid = 2で 2 つの行をロックし、 2 つのトランザクションが次の順序で実行されるとします。
- トランザクションA は行をid = 1でロックします。
- トランザクションB は最初のステートメントを実行し、行をid = 2でロックします。
- トランザクションB は 2 番目のステートメントを実行し、 id = 1で行をロックしようとしますが、これはトランザクション A によってブロックされます。
- トランザクションA はid = 2で行をロックしようとしますが、トランザクション B によってブロックされ、デッドロックが発生します。
この場合、他のトランザクションをブロックしているトランザクションAのステートメントが、現在実行中のステートメントでもあるため、現在のステートメントに対する悲観的ロックを解消し(トランザクションBの実行を継続できるように)、現在のステートメントを再試行できます。TiDBは、内部的にキーハッシュを使用して、これが当てはまるかどうかを判断します。
再試行可能なデッドロックが発生した場合、内部の自動再試行はトランザクションエラーを引き起こさないため、クライアントからは透過的に行われます。ただし、この状況が頻繁に発生すると、パフォーマンスに影響が出る可能性があります。その場合、TiDBログにsingle statement deadlock, retry statement表示されます。
例1
テーブル定義と初期データが次のとおりであると仮定します。
CREATE TABLE t (id int primary key, v int);
INSERT INTO t VALUES (1, 10), (2, 20);
2 つのトランザクションは次の順序で実行されます。
| トランザクション1 | トランザクション2 | 説明 | 
|---|---|---|
| BEGIN; | ||
| BEGIN; | ||
| UPDATE t SET v = 11 WHERE id = 1; | ||
| UPDATE t SET v = 21 WHERE id = 2; | ||
| UPDATE t SET v = 12 WHERE id = 2; | トランザクション1 はブロックされます。 | |
| UPDATE t SET v = 22 WHERE id = 1; | トランザクション2 はデッドロック エラーを報告します。 | 
次に、トランザクション2がデッドロックエラーを報告します。この時点で、テーブルDEADLOCKSクエリを実行します。
SELECT * FROM INFORMATION_SCHEMA.DEADLOCKS;
期待される出力は次のとおりです。
+-------------+----------------------------+-----------+--------------------+------------------------------------------------------------------+-----------------------------------------+----------------------------------------+----------------------------------------------------------------------------------------------------+--------------------+
| DEADLOCK_ID | OCCUR_TIME                 | RETRYABLE | TRY_LOCK_TRX_ID    | CURRENT_SQL_DIGEST                                               | CURRENT_SQL_DIGEST_TEXT                 | KEY                                    | KEY_INFO                                                                                           | TRX_HOLDING_LOCK   |
+-------------+----------------------------+-----------+--------------------+------------------------------------------------------------------+-----------------------------------------+----------------------------------------+----------------------------------------------------------------------------------------------------+--------------------+
|           1 | 2021-08-05 11:09:03.230341 |         0 | 426812829645406216 | 22230766411edb40f27a68dadefc63c6c6970d5827f1e5e22fc97be2c4d8350d | update `t` set `v` = ? where `id` = ? ; | 7480000000000000355F728000000000000002 | {"db_id":1,"db_name":"test","table_id":53,"table_name":"t","handle_type":"int","handle_value":"2"} | 426812829645406217 |
|           1 | 2021-08-05 11:09:03.230341 |         0 | 426812829645406217 | 22230766411edb40f27a68dadefc63c6c6970d5827f1e5e22fc97be2c4d8350d | update `t` set `v` = ? where `id` = ? ; | 7480000000000000355F728000000000000001 | {"db_id":1,"db_name":"test","table_id":53,"table_name":"t","handle_type":"int","handle_value":"1"} | 426812829645406216 |
+-------------+----------------------------+-----------+--------------------+------------------------------------------------------------------+-----------------------------------------+----------------------------------------+----------------------------------------------------------------------------------------------------+--------------------+
テーブルDEADLOCKSに2行のデータが生成されます。両行のフィールドDEADLOCK_IDは1であり、両行の情報が同じデッドロックエラーに属していることを意味します。1行目は、キー"7480000000000000355F728000000000000002"において、ID "426812829645406216"のトランザクションがID "426812829645406217"のトランザクションによってブロックされていることを示しています。2行目は、キー"7480000000000000355F728000000000000001"において、ID "426812829645406217"のトランザクションがID 426812829645406216のトランザクションによってブロックされていることを示しています。これにより相互ブロッキングが発生し、デッドロックが発生します。
例2
DEADLOCKSテーブルをクエリして次の結果が得られたとします。
+-------------+----------------------------+-----------+--------------------+------------------------------------------------------------------+-----------------------------------------+----------------------------------------+----------------------------------------------------------------------------------------------------+--------------------+
| DEADLOCK_ID | OCCUR_TIME                 | RETRYABLE | TRY_LOCK_TRX_ID    | CURRENT_SQL_DIGEST                                               | CURRENT_SQL_DIGEST_TEXT                 | KEY                                    | KEY_INFO                                                                                           | TRX_HOLDING_LOCK   |
+-------------+----------------------------+-----------+--------------------+------------------------------------------------------------------+-----------------------------------------+----------------------------------------+----------------------------------------------------------------------------------------------------+--------------------+
|           1 | 2021-08-05 11:09:03.230341 |         0 | 426812829645406216 | 22230766411edb40f27a68dadefc63c6c6970d5827f1e5e22fc97be2c4d8350d | update `t` set `v` = ? where `id` = ? ; | 7480000000000000355F728000000000000002 | {"db_id":1,"db_name":"test","table_id":53,"table_name":"t","handle_type":"int","handle_value":"2"} | 426812829645406217 |
|           1 | 2021-08-05 11:09:03.230341 |         0 | 426812829645406217 | 22230766411edb40f27a68dadefc63c6c6970d5827f1e5e22fc97be2c4d8350d | update `t` set `v` = ? where `id` = ? ; | 7480000000000000355F728000000000000001 | {"db_id":1,"db_name":"test","table_id":53,"table_name":"t","handle_type":"int","handle_value":"1"} | 426812829645406216 |
|           2 | 2021-08-05 11:09:21.252154 |         0 | 426812832017809412 | 22230766411edb40f27a68dadefc63c6c6970d5827f1e5e22fc97be2c4d8350d | update `t` set `v` = ? where `id` = ? ; | 7480000000000000355F728000000000000002 | {"db_id":1,"db_name":"test","table_id":53,"table_name":"t","handle_type":"int","handle_value":"2"} | 426812832017809413 |
|           2 | 2021-08-05 11:09:21.252154 |         0 | 426812832017809413 | 22230766411edb40f27a68dadefc63c6c6970d5827f1e5e22fc97be2c4d8350d | update `t` set `v` = ? where `id` = ? ; | 7480000000000000355F728000000000000003 | {"db_id":1,"db_name":"test","table_id":53,"table_name":"t","handle_type":"int","handle_value":"3"} | 426812832017809414 |
|           2 | 2021-08-05 11:09:21.252154 |         0 | 426812832017809414 | 22230766411edb40f27a68dadefc63c6c6970d5827f1e5e22fc97be2c4d8350d | update `t` set `v` = ? where `id` = ? ; | 7480000000000000355F728000000000000001 | {"db_id":1,"db_name":"test","table_id":53,"table_name":"t","handle_type":"int","handle_value":"1"} | 426812832017809412 |
+-------------+----------------------------+-----------+--------------------+------------------------------------------------------------------+-----------------------------------------+----------------------------------------+----------------------------------------------------------------------------------------------------+--------------------+
上記のクエリ結果のDEADLOCK_ID列目を見ると、最初の2行はデッドロックエラーの情報を表しており、互いに待機する2つのトランザクションがデッドロックを形成していることがわかります。次の3行は別のデッドロックエラーの情報を表しており、循環的に待機する3つのトランザクションがデッドロックを形成しています。
クラスターデッドロック
CLUSTER_DEADLOCKSテーブルは、クラスター全体の各 TiDB ノードの最近のデッドロック エラーに関する情報を返します。これは、各ノードのDEADLOCKSテーブルの情報を組み合わせたものです。5 CLUSTER_DEADLOCKSは、異なる TiDB ノードを区別するために、ノードの IP アドレスとポートを表示する追加のINSTANCE列も含まれています。
DEADLOCK_IDグローバルな一意性が保証されないため、 CLUSTER_DEADLOCKSテーブルのクエリ結果では、結果セット内の異なるデッドロック エラーの情報を区別するために、 INSTANCEとDEADLOCK_ID一緒に使用する必要があることに注意してください。
USE INFORMATION_SCHEMA;
DESC CLUSTER_DEADLOCKS;
出力は次のようになります。
+-------------------------+---------------------+------+------+---------+-------+
| Field                   | Type                | Null | Key  | Default | Extra |
+-------------------------+---------------------+------+------+---------+-------+
| INSTANCE                | varchar(64)         | YES  |      | NULL    |       |
| DEADLOCK_ID             | bigint(21)          | NO   |      | NULL    |       |
| OCCUR_TIME              | timestamp(6)        | YES  |      | NULL    |       |
| RETRYABLE               | tinyint(1)          | NO   |      | NULL    |       |
| TRY_LOCK_TRX_ID         | bigint(21) unsigned | NO   |      | NULL    |       |
| CURRENT_SQL_DIGEST      | varchar(64)         | YES  |      | NULL    |       |
| CURRENT_SQL_DIGEST_TEXT | text                | YES  |      | NULL    |       |
| KEY                     | text                | YES  |      | NULL    |       |
| KEY_INFO                | text                | YES  |      | NULL    |       |
| TRX_HOLDING_LOCK        | bigint(21) unsigned | NO   |      | NULL    |       |
+-------------------------+---------------------+------+------+---------+-------+