行き詰まり
表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
同じデッドロック イベントを示します。 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
の詳細情報です。KEY_INFO
セクションを参照してください。TRX_HOLDING_LOCK
: 現在キーのロックを保持し、ブロックを引き起こしているトランザクションの ID。この ID はトランザクションのstart_ts
でもあります。
DEADLOCKS
テーブルに記録できるデッドロック イベントの最大数を調整するには、TiDB 構成ファイルのpessimistic-txn.deadlock-history-capacity
構成を調整します。デフォルトでは、最近の 10 件のデッドロック イベントの情報がテーブルに記録されます。
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_name
取得できず、テーブルがパーティションテーブルでindex_name
db_id
どうかを区別できません。
ノート:
パーティショニングが有効になっているテーブルからキーが取得され、クエリ中に何らかの理由 (キーが属するテーブルが削除されたなど) によりキーが属するスキーマの情報をクエリできない場合、IDキーが属するパーティションの名前が
table_id
フィールドに表示される場合があります。これは、TiDB が複数の独立したテーブルのキーをエンコードするのと同じ方法で、異なるパーティションのキーをエンコードするためです。したがって、スキーマ情報が欠落している場合、TiDB はキーがパーティション化されていないテーブルに属しているのか、テーブルの 1 つのパーティションに属しているのかを確認できません。
再試行可能なデッドロック エラー
ノート:
DEADLOCKS
テーブルは、デフォルトでは再試行可能なデッドロック エラーの情報を収集しません。テーブルで再試行可能なデッドロック エラー情報を収集する場合は、TiDB 構成ファイルで値pessimistic-txn.deadlock-history-collect-retryable
を調整できます。
トランザクション 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 | 説明 |
---|---|---|
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
です。これは、両方の行の情報が同じデッドロック エラーに属していることを意味します。最初の行は、キー"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 行は合わせて別のデッドロック エラーの情報を表し、1 つのサイクルで待機する 3 つのトランザクションがデッドロックを形成します。
CLUSTER_DEADLOCKS
CLUSTER_DEADLOCKS
テーブルは、クラスター全体の各 TiDB ノードで最近発生したデッドロック エラーに関する情報を返します。これは、各ノードのDEADLOCKS
テーブルの情報を組み合わせたものです。 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 | |
+-------------------------+---------------------+------+------+---------+-------+