diff --git a/TOC.md b/TOC.md index 9a8e703535bc..f50f17e4e116 100644 --- a/TOC.md +++ b/TOC.md @@ -422,7 +422,9 @@ + [`COLLATIONS`](/information-schema/information-schema-collations.md) + [`COLLATION_CHARACTER_SET_APPLICABILITY`](/information-schema/information-schema-collation-character-set-applicability.md) + [`COLUMNS`](/information-schema/information-schema-columns.md) + + [`DATA_LOCK_WAITS`](/information-schema/information-schema-data-lock-waits.md) + [`DDL_JOBS`](/information-schema/information-schema-ddl-jobs.md) + + [`DEADLOCKS`](/information-schema/information-schema-deadlocks.md) + [`ENGINES`](/information-schema/information-schema-engines.md) + [`INSPECTION_RESULT`](/information-schema/information-schema-inspection-result.md) + [`INSPECTION_RULES`](/information-schema/information-schema-inspection-rules.md) @@ -443,6 +445,7 @@ + [`TIDB_HOT_REGIONS`](/information-schema/information-schema-tidb-hot-regions.md) + [`TIDB_INDEXES`](/information-schema/information-schema-tidb-indexes.md) + [`TIDB_SERVERS_INFO`](/information-schema/information-schema-tidb-servers-info.md) + + [`TIDB_TRX`](/information-schema/information-schema-tidb-trx.md) + [`TIFLASH_REPLICA`](/information-schema/information-schema-tiflash-replica.md) + [`TIKV_REGION_PEERS`](/information-schema/information-schema-tikv-region-peers.md) + [`TIKV_REGION_STATUS`](/information-schema/information-schema-tikv-region-status.md) diff --git a/information-schema/information-schema-data-lock-waits.md b/information-schema/information-schema-data-lock-waits.md new file mode 100644 index 000000000000..2aa258e7429f --- /dev/null +++ b/information-schema/information-schema-data-lock-waits.md @@ -0,0 +1,86 @@ +--- +title: DATA_LOCK_WAITS +summary: 了解 information_schema 表 `DATA_LOCK_WAITS`。 +--- + +# DATA_LOCK_WAITS + +`DATA_LOCK_WAITS` 表展示了集群中所有 TiKV 节点上当前正在发生的悲观锁等锁的情况。 + +> **警告:** +> +> 该功能目前为实验性功能,表结构的定义和行为在未来版本中可能有较大改动。 + +{{< copyable "sql" >}} + +```sql +USE information_schema; +DESC data_lock_waits; +``` + +```sql ++------------------------+---------------------+------+------+---------+-------+ +| Field | Type | Null | Key | Default | Extra | ++------------------------+---------------------+------+------+---------+-------+ +| KEY | varchar(64) | NO | | NULL | | +| TRX_ID | bigint(21) unsigned | NO | | NULL | | +| CURRENT_HOLDING_TRX_ID | bigint(21) unsigned | NO | | NULL | | +| SQL_DIGEST | varchar(64) | YES | | NULL | | ++------------------------+---------------------+------+------+---------+-------+ +``` + +`DATA_LOCK_WAITS` 表中各列的字段含义如下: + +* `KEY`:正在发生等锁的 KEY,以十六进制编码的形式显示。 +* `TRX_ID`:正在等锁的事务 ID,即 `start_ts`。 +* `CURRENT_HOLDING_TRX_ID`:当前持有锁的事务 ID,即 `start_ts`。 +* `SQL_DIGEST`:当前正在等锁的事务中被阻塞的 SQL 语句的 Digest。 + +> **警告:** +> +> * 该表中的信息是在查询时,从所有 TiKV 节点实时获取的。目前,即使加上了 `WHERE` 查询条件,也无法避免对所有 TiKV 节点都进行信息收集。如果集群规模很大、负载很高,查询该表有造成性能抖动的潜在风险,因此请根据实际情况使用。 +> * 来自不同 TiKV 节点的信息不一定是同一时间点的快照。 + +## 示例 + +{{< copyable "sql" >}} + +```sql +select * from information_schema.data_lock_waits\G +``` + +```sql +*************************** 1. row *************************** + KEY: 7480000000000000355f728000000000000002 + TRX_ID: 425405024158875649 +CURRENT_HOLDING_TRX_ID: 425405016242126849 + SQL_DIGEST: f7530877a35ae65300c42250abd8bc731bbaf0a7cabc05dab843565230611bb22 +2 rows in set (0.01 sec) +``` + +以上查询结果显示,ID 为 `425405024158875649` 的事务在执行 Digest 为 `"f7530877a35ae65300c42250abd8bc731bbaf0a7cabc05dab843565230611bb22"` 的语句的过程中,试图在 `"7480000000000000355f728000000000000002"` 这个 key 上获取悲观锁,但是该 key 目前被 ID 为 `425405016242126849` 的事务持有。 + +## SQL Digest + +`DATA_LOCK_WAITS` 表中会记录 SQL Digest,并不记录 SQL 原文。 + +SQL Digest 是 SQL 归一化之后的哈希值。如需查找 SQL Digest 对应的 SQL 原文,请进行以下操作之一: + +- 对于当前 TiDB 节点在最近一段时间内执行过的语句,你可以从 `STATEMENTS_SUMMARY` 或 `STATEMENTS_SUMMARY_HISTORY` 中根据 SQL Digest 查找到对应的 SQL 原文。 +- 对于整个集群所有 TiDB 节点在最近一段时间内执行过的语句,你可以从 `CLUSTER_STATEMENTS_SUMMARY` 或`CLUSTER_STATEMENTS_SUMMARY_HISTORY` 中根据 SQL Digest 查找到对应的 SQL 原文。 + +{{< copyable "sql" >}} + +```sql +select digest, digest_text from information_schema.statements_summary where digest = "f7530877a35ae65300c42250abd8bc731bbaf0a7cabc05dab843565230611bb2"; +``` + +```sql ++------------------------------------------------------------------+---------------------------------------+ +| digest | digest_text | ++------------------------------------------------------------------+---------------------------------------+ +| f7530877a35ae65300c42250abd8bc731bbaf0a7cabc05dab843565230611bb2 | update `t` set `v` = ? where `id` = ? | ++------------------------------------------------------------------+---------------------------------------+ +``` + +关于 SQL Digest 和 `STATEMENTS_SUMMARY`、`STATEMENTS_SUMMARY_HISTORY` 、`CLUSTER_STATEMENTS_SUMMARY`、`CLUSTER_STATEMENTS_SUMMARY_HISTORY` 表的详细说明,请参阅 [Statement Summary Tables](/statement-summary-tables.md)。 diff --git a/information-schema/information-schema-deadlocks.md b/information-schema/information-schema-deadlocks.md new file mode 100644 index 000000000000..4cc3769e7bc8 --- /dev/null +++ b/information-schema/information-schema-deadlocks.md @@ -0,0 +1,196 @@ +--- +title: DEADLOCKS +summary: 了解 information_schema 表 `DEADLOCKS`。 +--- + +# DEADLOCKS + +`DEADLOCKS` 表提供当前 TiDB 节点上最近发生的若干次死锁错误的信息。 + +> **警告:** +> +> 该功能目前为实验性功能,表结构的定义和行为在未来版本中可能有较大改动。 + +{{< copyable "sql" >}} + +```sql +USE information_schema; +DESC deadlocks; +``` + +```sql ++--------------------+---------------------+------+------+---------+-------+ +| 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 | | +| KEY | text | YES | | NULL | | +| TRX_HOLDING_LOCK | bigint(21) unsigned | NO | | NULL | | ++--------------------+---------------------+------+------+---------+-------+ +``` + +`DEADLOCKS` 表中需要用多行来表示同一个死锁事件,每行显示参与死锁的其中一个事务的信息。当该 TiDB 节点记录了多次死锁错误时,需要按照 `DEADLOCK_ID` 列来区分,相同的 `DEADLOCK_ID` 表示同一个死锁事件。需要注意,`DEADLOCK_ID` **并不保证全局唯一,也不会持久化**,因而其只能在同一个结果集里表示同一个死锁事件。 + +`DEADLOCKS` 表中各列的字段含义如下: + +* `DEADLOCK_ID`:死锁事件的 ID。当表内存在多次死锁错误的信息时,需要使用该列来区分属于不同死锁错误的行。 +* `OCCUR_TIME`:发生该次死锁错误的时间。 +* `RETRYABLE`:该次死锁错误是否可重试。目前暂不支持收集可重试的死锁错误的信息,因而该字段值恒为 0。关于可重试的死锁错误的说明,参见[可重试的死锁错误](#可重试的死锁错误)小节。 +* `TRY_LOCK_TRX_ID`:试图上锁的事务 ID,即事务的 `start_ts`。 +* `CURRENT_SQL_DIGEST`:试图上锁的事务中当前正在执行的 SQL 语句的 Digest。 +* `KEY`:该事务试图上锁、但是被阻塞的 key,以十六进制编码的形式显示。 +* `TRX_HOLDING_LOCK`:该 key 上当前持锁并导致阻塞的事务 ID,即事务的 `start_ts`。 + +要调整 `DEADLOCKS` 表中可以容纳的死锁事件数量,可通过 TiDB 配置文件中的 [`pessimistic-txn.deadlock-history-capacity`](/tidb-configuration-file.md#deadlock-history-capacity) 配置项进行调整,默认容纳最近 10 次死锁错误的信息。 + +## 示例 1 + +假设有如下表定义和初始数据: + +{{< copyable "sql" >}} + +```sql +create table t (id int primary key, v int); +insert into t values (1, 10), (2, 20); +``` + +使两个事务按如下顺序执行: + +| 事务 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` 表,将得到如下结果: + +{{< copyable "sql" >}} + +```sql +select * from information_schema.deadlocks; +``` + +```sql ++-------------+----------------------------+-----------+--------------------+------------------------------------------------------------------+----------------------------------------+--------------------+ +| DEADLOCK_ID | OCCUR_TIME | RETRYABLE | TRY_LOCK_TRX_ID | CURRENT_SQL_DIGEST | KEY | TRX_HOLDING_LOCK | ++-------------+----------------------------+-----------+--------------------+------------------------------------------------------------------+----------------------------------------+--------------------+ +| 1 | 2021-06-04 08:22:38.765699 | 0 | 425405959304904707 | 22230766411edb40f27a68dadefc63c6c6970d5827f1e5e22fc97be2c4d8350d | 7480000000000000385F728000000000000002 | 425405959304904708 | +| 1 | 2021-06-04 08:22:38.765699 | 0 | 425405959304904708 | 22230766411edb40f27a68dadefc63c6c6970d5827f1e5e22fc97be2c4d8350d | 7480000000000000385F728000000000000001 | 425405959304904707 | ++-------------+----------------------------+-----------+--------------------+------------------------------------------------------------------+----------------------------------------+--------------------+ +``` + +该表中产生了两行数据,两行的 `DEADLOCK_ID` 字段皆为 1,表示这两行数据包含同一次死锁错误的信息。第一行显示 ID 为 `425405959304904707` 的事务,在 `"7480000000000000385F728000000000000002"` 这个 key 上,被 ID 为 `"425405959304904708"` 的事务阻塞了;第二行则显示 ID 为 `"425405959304904708"` 的事务在 `"7480000000000000385F728000000000000001"` 这个 key 上被 ID 为 `425405959304904707` 的事务阻塞了,构成了相互阻塞的状态,形成了死锁。 + +## 示例 2 + +假设查询 `DEADLOCKS` 表得到了如下结果集: + +```sql ++-------------+----------------------------+-----------+--------------------+------------------------------------------------------------------+----------------------------------------+--------------------+ +| DEADLOCK_ID | OCCUR_TIME | RETRYABLE | TRY_LOCK_TRX_ID | CURRENT_SQL_DIGEST | KEY | TRX_HOLDING_LOCK | ++-------------+----------------------------+-----------+--------------------+------------------------------------------------------------------+----------------------------------------+--------------------+ +| 1 | 2021-06-04 08:22:38.765699 | 0 | 425405959304904707 | 22230766411edb40f27a68dadefc63c6c6970d5827f1e5e22fc97be2c4d8350d | 7480000000000000385F728000000000000002 | 425405959304904708 | +| 1 | 2021-06-04 08:22:38.765699 | 0 | 425405959304904708 | 22230766411edb40f27a68dadefc63c6c6970d5827f1e5e22fc97be2c4d8350d | 7480000000000000385F728000000000000001 | 425405959304904707 | +| 2 | 2021-06-04 08:22:56.795410 | 0 | 425405961664462853 | 22230766411edb40f27a68dadefc63c6c6970d5827f1e5e22fc97be2c4d8350d | 7480000000000000385F728000000000000002 | 425405961664462854 | +| 2 | 2021-06-04 08:22:56.795410 | 0 | 425405961664462854 | 22230766411edb40f27a68dadefc63c6c6970d5827f1e5e22fc97be2c4d8350d | 7480000000000000385F728000000000000003 | 425405961664462855 | +| 2 | 2021-06-04 08:22:56.795410 | 0 | 425405961664462855 | 22230766411edb40f27a68dadefc63c6c6970d5827f1e5e22fc97be2c4d8350d | 7480000000000000385F728000000000000001 | 425405961664462853 | ++-------------+----------------------------+-----------+--------------------+------------------------------------------------------------------+----------------------------------------+--------------------+ +``` + +以上查询结果中的 `DEADLOCK_ID` 列表明,前两行共同表示一次死锁错误的信息,两条事务相互等待构成了死锁;而后三行共同表示另一次死锁信息,三个事务循环等待构成了死锁。 + +## 可重试的死锁错误 + +> **注意:** +> +> 目前,`DEADLOCKS` 表暂不支持收集可重试的死锁错误相关的信息。 + +当事务 A 被另一个事务已经持有的锁阻塞,而事务 B 直接或间接地被当前事务持有的锁阻塞,将会引发一个死锁错误。这里: + ++ 情况一:事务 B 可能(直接或间接地)被事务 A 之前已经执行完的语句产生的锁阻塞 ++ 情况二:事务 B 也可能被事务 A 目前正在执行的语句阻塞 + +对于情况一,TiDB 将会向事务 A 的客户端报告死锁错误,并终止该事务;而对于情况二,事务 A 当前正在执行的语句将在 TiDB 内部被自动重试。例如,假设事务 A 执行了如下语句: + +{{< copyable "sql" >}} + +```sql +update t set v = v + 1 where id = 1 or id = 2; +``` + +事务 B 则先后执行如下两条语句: + +{{< copyable "sql" >}} + +```sql +update t set v = 4 where id = 2; +update t set v = 2 where id = 1; +``` + +那么如果事务 A 先后对 `id = 1` 和 `id = 2` 的两行分别上锁,且两个事务以如下时序运行: + +1. 事务 A 对 `id = 1` 的行上锁 +2. 事务 B 执行第一条语句并对 `id = 2` 的行上锁 +3. 事务 B 执行第二条语句试图对 `id = 1` 的行上锁,被事务 A 阻塞 +4. 事务 A 试图对 `id = 2` 的行上锁,被 B 阻塞,形成死锁 + +对于情况二,由于事务 A 阻塞其它事务的语句也是当前正在执行的语句,因而可以解除当前语句所上的悲观锁(使得事务 B 可以继续运行),并重试当前语句。TiDB 内部使用 key 的 hash 来判断是否属于这种情况。 + +当可重试的死锁发生时,内部自动重试并不会引起事务报错,因而对客户端透明,但是这种情况的频繁发生可能影响性能。当这种情况发生时,在 TiDB 的日志中可以观察到 `single statement deadlock, retry statement` 字样的日志。 + +## CLUSTER_DEADLOCKS + +`CLUSTER_DEADLOCKS` 表返回整个集群上每个 TiDB 节点中最近发生的数次死锁错误的信息,即将每个节点上的 `DEADLOCKS` 表内的信息合并在一起。`CLUSTER_DEADLOCKS` 还包含额外的 `INSTANCE` 列展示所属节点的 IP 地址和端口,用以区分不同的 TiDB 节点。 + +需要注意的是,由于 `DEADLOCK_ID` 并不保证全局唯一,所以在 `CLUSTER_DEADLOCKS` 表的查询结果中,需要 `INSTANCE` 和 `DEADLOCK_ID` 两个字段共同区分结果集中的不同死锁错误的信息。 + +{{< copyable "sql" >}} + +```sql +USE information_schema; +DESC cluster_deadlocks; +``` + +```sql ++--------------------+---------------------+------+------+---------+-------+ +| 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 | | +| KEY | text | YES | | NULL | | +| TRX_HOLDING_LOCK | bigint(21) unsigned | NO | | NULL | | ++--------------------+---------------------+------+------+---------+-------+ +``` + +## SQL Digest + +`DEADLOCKS` 表记录 SQL Digest,并不记录 SQL 原文。 + +SQL Digest 是 SQL 归一化之后的哈希值。如需查找 SQL Digest 对应的 SQL 原文,请进行以下任一操作: + +- 对于当前 TiDB 节点在最近一段时间内执行过的语句,你可以从 `STATEMENTS_SUMMARY` 或 `STATEMENTS_SUMMARY_HISTORY` 中根据 SQL Digest 查找到对应的 SQL 原文。 +- 对于整个集群所有 TiDB 节点在最近一段时间内执行过的语句,你可以从 `CLUSTER_STATEMENTS_SUMMARY` 或`CLUSTER_STATEMENTS_SUMMARY_HISTORY` 中根据 SQL Digest 查找到对应的 SQL 原文。 + +{{< copyable "sql" >}} + +```sql +select digest, digest_text from information_schema.statements_summary where digest = "f7530877a35ae65300c42250abd8bc731bbaf0a7cabc05dab843565230611bb2"; +``` + +```sql ++------------------------------------------------------------------+---------------------------------------+ +| digest | digest_text | ++------------------------------------------------------------------+---------------------------------------+ +| f7530877a35ae65300c42250abd8bc731bbaf0a7cabc05dab843565230611bb2 | update `t` set `v` = ? where `id` = ? | ++------------------------------------------------------------------+---------------------------------------+ +``` + +关于 SQL Digest 和 `STATEMENTS_SUMMARY`、`STATEMENTS_SUMMARY_HISTORY`、`CLUSTER_STATEMENTS_SUMMARY`、`CLUSTER_STATEMENTS_SUMMARY_HISTORY` 表的详细说明,请参阅 [Statement Summary Tables](/statement-summary-tables.md)。 diff --git a/information-schema/information-schema-tidb-trx.md b/information-schema/information-schema-tidb-trx.md new file mode 100644 index 000000000000..a919efbca4c5 --- /dev/null +++ b/information-schema/information-schema-tidb-trx.md @@ -0,0 +1,137 @@ +--- +title: TIDB_TRX +summary: 了解 information_schema 表 `TIDB_TRX`。 +--- + +# TIDB_TRX + +`TIDB_TRX` 表提供了当前 TiDB 节点上正在执行的事务的信息。 + +> **警告:** +> +> * 该功能目前为实验性功能,表结构的定义和行为在未来版本中可能有较大改动。 +> * 目前 `TIDB_TRX` 表暂不支持显示 TiDB 内部事务相关的信息。 + +{{< copyable "sql" >}} + +```sql +USE information_schema; +DESC tidb_trx; +``` + +```sql ++--------------------+---------------------------------------------------------+------+------+---------+-------+ +| Field | Type | Null | Key | Default | Extra | ++--------------------+---------------------------------------------------------+------+------+---------+-------+ +| ID | bigint(21) unsigned | NO | PRI | NULL | | +| START_TIME | timestamp(6) | YES | | NULL | | +| CURRENT_SQL_DIGEST | varchar(64) | YES | | NULL | | +| STATE | enum('Normal','LockWaiting','Committing','RollingBack') | YES | | NULL | | +| WAITING_START_TIME | timestamp(6) | YES | | NULL | | +| MEM_BUFFER_KEYS | bigint(64) | YES | | NULL | | +| MEM_BUFFER_BYTES | bigint(64) | YES | | NULL | | +| SESSION_ID | bigint(21) unsigned | YES | | NULL | | +| USER | varchar(16) | YES | | NULL | | +| DB | varchar(64) | YES | | NULL | | +| ALL_SQL_DIGESTS | text | YES | | NULL | | ++--------------------+---------------------------------------------------------+------+------+---------+-------+ +``` + +`TIDB_TRX` 表中各列的字段含义如下: + +* `ID`:事务 ID,即事务的开始时间戳 `start_ts`。 +* `START_TIME`:事务的开始时间,即事务的 `start_ts` 所对应的物理时间。 +* `CURRENT_SQL_DIGEST`:该事务当前正在执行的 SQL 语句的 Digest。 +* `STATE`:该事务当前所处的状态。其可能的值包括: + * `Normal`:事务正在正常执行,或者处于闲置状态。 + * `LockWaiting`:事务处于正在等待悲观锁上锁完成的状态。需要注意的是,事务刚开始进行悲观锁上锁操作时即进入该状态,无论是否有被其它事务阻塞。 + * `Committing`:事务正在提交过程中。 + * `RollingBack`:事务正在回滚过程中。 +* `WAITING_START_TIME`:当 `STATE` 值为 `LockWaiting` 时,该列显示等待的开始时间。 +* `MEM_BUFFER_KEYS`:当前事务写入内存缓冲区的 key 的个数。 +* `MEM_BUFFER_BYTES`:当前事务写入内存缓冲区的 key 和 value 的总字节数。 +* `SESSION_ID`:该事务所属的 session 的 ID。 +* `USER`:执行该事务的用户名。 +* `DB`:执行该事务的 session 当前的默认数据库名。 +* `ALL_SQL_DIGESTS`:该事务已经执行过的语句的 Digest 的列表。每个事务最多记录前 50 条语句。 + +## 示例 + +{{< copyable "sql" >}} + +```sql +select * from information_schema.tidb_trx\G +``` + +```sql +*************************** 1. row *************************** + ID: 425403705115541506 + START_TIME: 2021-06-04 05:59:10.691000 +CURRENT_SQL_DIGEST: NULL + STATE: Normal +WAITING_START_TIME: NULL + MEM_BUFFER_KEYS: 2 + MEM_BUFFER_BYTES: 48 + SESSION_ID: 7 + USER: root + DB: test + ALL_SQL_DIGESTS: [e6f07d43b5c21db0fbb9a31feac2dc599787763393dd5acbfad80e247eb02ad5, 04fa858fa491c62d194faec2ab427261cc7998b3f1ccf8f6844febca504cb5e9, f7530877a35ae65300c42250abd8bc731bbaf0a7cabc05dab843565230611bb2] +1 row in set (0.00 sec) +``` + +此示例的查询结果表示:当前节点有一个事务正在执行(`STATE` 为 `Normal`),该事务目前处于闲置状态(`CURRENT_SQL_DIGEST` 为 `NULL`), 该事务已经执行过 3 条语句(`ALL_SQL_DIGESTS` 列表中有三条记录,分别为执行过的 3 条语句的 Digest)。 + +## CLUSTER_TIDB_TRX + +`TIDB_TRX` 表仅提供单个 TiDB 节点中正在执行的事务信息。如果要查看整个集群上所有 TiDB 节点中正在执行的事务信息,需要查询 `CLUSTER_TIDB_TRX` 表。与 `TIDB_TRX` 表的查询结果相比,`CLUSTER_TIDB_TRX` 表的查询结果额外包含了 `INSTANCE` 字段。`INSTANCE` 字段展示了集群中各节点的 IP 地址和端口,用于区分事务所在的 TiDB 节点。 + +{{< copyable "sql" >}} + +```sql +USE information_schema; +DESC cluster_tidb_trx; +``` + +```sql ++--------------------+---------------------------------------------------------+------+------+---------+-------+ +| Field | Type | Null | Key | Default | Extra | ++--------------------+---------------------------------------------------------+------+------+---------+-------+ +| INSTANCE | varchar(64) | YES | | NULL | | +| ID | bigint(21) unsigned | NO | PRI | NULL | | +| START_TIME | timestamp(6) | YES | | NULL | | +| CURRENT_SQL_DIGEST | varchar(64) | YES | | NULL | | +| STATE | enum('Normal','LockWaiting','Committing','RollingBack') | YES | | NULL | | +| WAITING_START_TIME | timestamp(6) | YES | | NULL | | +| MEM_BUFFER_KEYS | bigint(64) | YES | | NULL | | +| MEM_BUFFER_BYTES | bigint(64) | YES | | NULL | | +| SESSION_ID | bigint(21) unsigned | YES | | NULL | | +| USER | varchar(16) | YES | | NULL | | +| DB | varchar(64) | YES | | NULL | | +| ALL_SQL_DIGESTS | text | YES | | NULL | | ++--------------------+---------------------------------------------------------+------+------+---------+-------+ +``` + +## SQL Digest + +`TIDB_TRX` 表只记录 SQL Digest,不记录 SQL 语句原文。 + +SQL Digest 是 SQL 归一化之后的哈希值。如需查找 SQL Digest 对应的 SQL 原文,请进行以下操作之一: + +- 对于当前 TiDB 节点在最近一段时间内执行过的语句,你可以从 `STATEMENTS_SUMMARY` 或 `STATEMENTS_SUMMARY_HISTORY` 中根据 SQL Digest 查找到对应的 SQL 原文。 +- 对于整个集群所有 TiDB 节点在最近一段时间内执行过的语句,你可以从 `CLUSTER_STATEMENTS_SUMMARY` 或`CLUSTER_STATEMENTS_SUMMARY_HISTORY` 中根据 SQL Digest 查找到对应的 SQL 原文。 + +{{< copyable "sql" >}} + +```sql +select digest, digest_text from information_schema.statements_summary where digest = "f7530877a35ae65300c42250abd8bc731bbaf0a7cabc05dab843565230611bb2"; +``` + +```sql ++------------------------------------------------------------------+---------------------------------------+ +| digest | digest_text | ++------------------------------------------------------------------+---------------------------------------+ +| f7530877a35ae65300c42250abd8bc731bbaf0a7cabc05dab843565230611bb2 | update `t` set `v` = ? where `id` = ? | ++------------------------------------------------------------------+---------------------------------------+ +``` + +关于 SQL Digest 和 `STATEMENTS_SUMMARY`、`STATEMENTS_SUMMARY_HISTORY` 、`CLUSTER_STATEMENTS_SUMMARY`、`CLUSTER_STATEMENTS_SUMMARY_HISTORY` 表的详细说明,请参阅 [Statement Summary Tables](/statement-summary-tables.md)。 diff --git a/information-schema/information-schema.md b/information-schema/information-schema.md index 7c91364e33b1..c422dceded48 100644 --- a/information-schema/information-schema.md +++ b/information-schema/information-schema.md @@ -55,6 +55,7 @@ Information Schema 提供了一种查看系统元数据的 ANSI 标准方法。 | [`CLIENT_ERRORS_SUMMARY_BY_USER`](/information-schema/client-errors-summary-by-user.md) | 汇总由客户端产生的错误和警告。 | | [`CLIENT_ERRORS_SUMMARY_GLOBAL`](/information-schema/client-errors-summary-global.md) | 汇总由客户端产生的错误和警告。 | | [`CLUSTER_CONFIG`](/information-schema/information-schema-cluster-config.md) | 提供有关整个 TiDB 集群的配置设置的详细信息。 | +| `CLUSTER_DEADLOCKS` | 提供 `DEADLOCKS` 表的集群级别的视图。 | | [`CLUSTER_HARDWARE`](/information-schema/information-schema-cluster-info.md) | 提供在每个 TiDB 组件上发现的底层物理硬件的详细信息。 | | [`CLUSTER_INFO`](/information-schema/information-schema-cluster-info.md) | 提供当前集群拓扑的详细信息。 | | [`CLUSTER_LOAD`](/information-schema/information-schema-cluster-load.md) | 提供集群中 TiDB 服务器的当前负载信息。 | @@ -62,9 +63,12 @@ Information Schema 提供了一种查看系统元数据的 ANSI 标准方法。 | `CLUSTER_PROCESSLIST` | 提供 `PROCESSLIST` 表的集群级别的视图。 | | `CLUSTER_SLOW_QUERY` | 提供 `SLOW_QUERY` 表的集群级别的视图。 | | `CLUSTER_STATEMENTS_SUMMARY` | 提供 `STATEMENTS_SUMMARY` 表的集群级别的视图。 | -| `CLUSTER_STATEMENTS_SUMMARY_HISTORY` | 提供 `CLUSTER_STATEMENTS_SUMMARY_HISTORY` 表的集群级别的视图。 | +| `CLUSTER_STATEMENTS_SUMMARY_HISTORY` | 提供 `STATEMENTS_SUMMARY_HISTORY` 表的集群级别的视图。 | +| `CLUSTER_TIDB_TRX` | 提供 `TIDB_TRX` 表的集群级别的视图。 | | [`CLUSTER_SYSTEMINFO`](/information-schema/information-schema-cluster-systeminfo.md) | 提供集群中服务器的内核参数配置的详细信息。 | +| [`DATA_LOCK_WAITS`](/information-schema/information-schema-data-lock-waits.md) | 提供 TiKV 服务器上的等锁信息。 | | [`DDL_JOBS`](/information-schema/information-schema-ddl-jobs.md) | 提供与 `ADMIN SHOW DDL JOBS` 类似的输出。 | +| [`DEADLOCKS`](/information-schema/information-schema-deadlocks.md) | 提供 TiDB 节点上最近发生的数次死锁错误的信息。 | | [`INSPECTION_RESULT`](/information-schema/information-schema-inspection-result.md) | 触发内部诊断检查。 | | [`INSPECTION_RULES`](/information-schema/information-schema-inspection-rules.md) | 进行的内部诊断检查的列表。 | | [`INSPECTION_SUMMARY`](/information-schema/information-schema-inspection-summary.md) | 重要监视指标的摘要报告。 | @@ -79,6 +83,7 @@ Information Schema 提供了一种查看系统元数据的 ANSI 标准方法。 | [`TIDB_HOT_REGIONS`](/information-schema/information-schema-tidb-hot-regions.md) | 提供有关哪些 Region 访问次数最多的统计信息。 | | [`TIDB_INDEXES`](/information-schema/information-schema-tidb-indexes.md) | 提供有关 TiDB 表的索引信息。 | | [`TIDB_SERVERS_INFO`](/information-schema/information-schema-tidb-servers-info.md) | 提供 TiDB 服务器的列表 | +| [`TIDB_TRX`](/information-schema/information-schema-tidb-trx.md) | 提供 TiDB 节点上正在执行的事务的信息。 | | [`TIFLASH_REPLICA`](/information-schema/information-schema-tiflash-replica.md) | 提供有关 TiFlash 副本的详细信息。 | | [`TIKV_REGION_PEERS`](/information-schema/information-schema-tikv-region-peers.md) | 提供 Region 存储位置的详细信息。 | | [`TIKV_REGION_STATUS`](/information-schema/information-schema-tikv-region-status.md) | 提供 Region 的统计信息。 | diff --git a/tidb-configuration-file.md b/tidb-configuration-file.md index b39c5c39069c..8c232a1b1ec5 100644 --- a/tidb-configuration-file.md +++ b/tidb-configuration-file.md @@ -599,6 +599,13 @@ TiDB 服务状态相关配置。 + 悲观事务中单个语句最大重试次数,重试次数超过该限制,语句执行将会报错。 + 默认值:256 +### deadlock-history-capacity + ++ 单个 TiDB 节点的 [`INFORMATION_SCHEMA.DEADLOCKS`](/information-schema/information-schema-deadlocks.md) 表最多可记录的死锁事件个数。当表的容量已满时,如果再次发生死锁错误,最早的一次死锁错误的信息将从表中移除。 ++ 默认值:10 ++ 最小值:0 ++ 最大值:10000 + ## experimental experimental 部分为 TiDB 实验功能相关的配置。该部分从 v3.1.0 开始引入。 diff --git a/troubleshoot-lock-conflicts.md b/troubleshoot-lock-conflicts.md index 6f7b576e7edd..a1b8265c29cf 100644 --- a/troubleshoot-lock-conflicts.md +++ b/troubleshoot-lock-conflicts.md @@ -78,7 +78,7 @@ Txn0 完成了 Prewrite,在 Commit 的过程中 Txn1 对该 key 发起了读 ```sh ./tidb-ctl decoder -f table_row -k "t\x00\x00\x00\x00\x00\x00\x00\x1c_r\x00\x00\x00\x00\x00\x00\x00\xfa" - + table_id: -9223372036854775780 row_id: -9223372036854775558 ``` @@ -238,4 +238,148 @@ TiDB 在使用悲观锁的情况下,多个事务之间出现了死锁,必定 处理建议: +* 如果难以确认产生死锁的原因,对于 v5.1 及以后的版本,建议尝试查询 `INFORMATION_SCHEMA.DEADLOCKS` 或 `INFORMATION_SCHEMA.CLUSTER_DEADLOCKS` 系统表来获取死锁的等待链信息。详情请参考[死锁错误](#死锁错误)小节和 [`DEADLOCKS` 表](/information-schema/information-schema-deadlocks.md)文档。 * 如果出现非常频繁,需要调整业务代码来降低死锁发生概率。 + +### 使用 Lock View 排查悲观锁相关的问题 + +自 v5.1 版本起,TiDB 支持 Lock View 功能。该功能在 `information_schema` 中内置了若干系统表,用于提供更多关于悲观锁的锁冲突和锁等待的信息。关于这些表的详细说明,请参考相关系统表的文档: + +* [`TIDB_TRX` 与 `CLUSTER_TIDB_TRX`](/information-schema/information-schema-tidb-trx.md):提供当前 TiDB 节点上或整个集群上所有运行中的事务的信息,包括事务是否处于等锁状态、等锁时间和事务曾经执行过的语句的 Digest 等信息。 +* [`DATA_LOCK_WAITS`](/information-schema/information-schema-data-lock-waits.md):提供关于 TiKV 内的悲观锁等锁信息,包括阻塞和被阻塞的事务的 `start_ts`、被阻塞的 SQL 语句的 Digest 和发生等待的 key。 +* [`DEADLOCKS` 与 `CLUSTER_DEADLOCKS`](/information-schema/information-schema-deadlocks.md):提供当前 TiDB 节点上或整个集群上最近发生过的若干次死锁的相关信息,包括死锁环中事务之间的等待关系、事务当前正在执行的语句的 Digest 和发生等待的 key。 + +> **警告:** +> +> 该功能目前为实验性功能,相关表结构的定义和行为在未来版本可能有较大改动。 + +以下为排查部分问题的示例。 + +#### 死锁错误 + +要获取最近发生的死锁错误的信息,可查询 `DEADLOCKS` 或 `CLUSTER_DEADLOCKS` 表,示例如下: + +{{< copyable "sql" >}} + +```sql +select * from information_schema.deadlocks; +``` + +```sql ++-------------+----------------------------+-----------+--------------------+------------------------------------------------------------------+----------------------------------------+--------------------+ +| DEADLOCK_ID | OCCUR_TIME | RETRYABLE | TRY_LOCK_TRX_ID | CURRENT_SQL_DIGEST | KEY | TRX_HOLDING_LOCK | ++-------------+----------------------------+-----------+--------------------+------------------------------------------------------------------+----------------------------------------+--------------------+ +| 1 | 2021-06-04 08:22:38.765699 | 0 | 425405959304904707 | 22230766411edb40f27a68dadefc63c6c6970d5827f1e5e22fc97be2c4d8350d | 7480000000000000385F728000000000000002 | 425405959304904708 | +| 1 | 2021-06-04 08:22:38.765699 | 0 | 425405959304904708 | 22230766411edb40f27a68dadefc63c6c6970d5827f1e5e22fc97be2c4d8350d | 7480000000000000385F728000000000000001 | 425405959304904707 | ++-------------+----------------------------+-----------+--------------------+------------------------------------------------------------------+----------------------------------------+--------------------+ +``` + +查询结果会显示死锁错误中多个事务之间的等待关系和各个事务当前正在执行的 SQL 语句的 Digest,以及发生冲突的 key。 + +你可以从 `STATEMENTS_SUMMARY` 或 `STATEMENTS_SUMMARY_HISTORY` 表中获取最近一段时间内,执行过的 SQL 语句的 Digest 所对应的归一化的 SQL 语句的文本(详见 [`STATEMENTS_SUMMARY` 和 `STATEMENTS_SUMMARY_HISTORY` 表](/statement-summary-tables.md))。你也可将获取到的结果直接与 `DEADLOCKS` 表进行 join 操作。注意:`STATEMENTS_SUMMARY` 中可能不包含所有 SQL 语句的信息,所以以下例子中使用了 left join: + +{{< copyable "sql" >}} + +```sql +select l.deadlock_id, l.occur_time, l.try_lock_trx_id, l.trx_holding_lock, s.digest_text from information_schema.deadlocks as l left join information_schema.statements_summary as s on l.current_sql_digest = s.digest; +``` + +```sql ++-------------+----------------------------+--------------------+--------------------+-----------------------------------------+ +| deadlock_id | occur_time | try_lock_trx_id | trx_holding_lock | digest_text | ++-------------+----------------------------+--------------------+--------------------+-----------------------------------------+ +| 1 | 2021-06-04 08:22:38.765699 | 425405959304904707 | 425405959304904708 | update `t` set `v` = ? where `id` = ? ; | +| 1 | 2021-06-04 08:22:38.765699 | 425405959304904708 | 425405959304904707 | update `t` set `v` = ? where `id` = ? ; | ++-------------+----------------------------+--------------------+--------------------+-----------------------------------------+ +``` + +#### 少数热点 key 造成锁排队 + +`DATA_LOCK_WAITS` 系统表提供 TiKV 节点上的等锁情况。查询该表时,TiDB 将自动从所有 TiKV 节点上获取当前时刻的等锁信息。当少数热点 key 频繁被上锁并阻塞较多事务时,你可以查询 `DATA_LOCK_WAITS` 表并按 key 对结果进行聚合,以尝试找出经常发生问题的 key: + +{{< copyable "sql" >}} + +```sql +select `key`, count(*) as `count` from information_schema.data_lock_waits group by `key` order by `count` desc; +``` + +```sql ++----------------------------------------+-------+ +| key | count | ++----------------------------------------+-------+ +| 7480000000000000415f728000000000000001 | 2 | +| 7480000000000000415f728000000000000002 | 1 | ++----------------------------------------+-------+ +``` + +为避免偶然性,你可考虑进行多次查询。 + +如果已知频繁出问题的 key,可尝试从 `TIDB_TRX` 或 `CLUSTER_TIDB_TRX` 表中获取试图上锁该 key 的事务的信息。 + +需要注意 `TIDB_TRX` 和 `CLUSTER_TIDB_TRX` 表所展示的信息也是对其进行查询的时刻正在运行的事务的信息,并不展示已经结束的事务。如果并发的事务数量很大,该查询的结果集也可能很大,可以考虑添加 limit 子句,或用 where 子句筛选出等锁时间较长的事务。需要注意,对 Lock View 中的多张表进行 join 时,不同表之间的数据并不保证在同一时刻获取,因而不同表中的信息可能并不同步。 + +{{< copyable "sql" >}} + +```sql +select trx.* from information_schema.data_lock_waits as l left join information_schema.tidb_trx as trx on l.trx_id = trx.id where l.key = "7480000000000000415f728000000000000001"\G +``` + +```sql +*************************** 1. row *************************** + ID: 425496938634543111 + START_TIME: 2021-06-08 08:46:48.341000 +CURRENT_SQL_DIGEST: a4e28cc182bdd18288e2a34180499b9404cd0ba07e3cc34b6b3be7b7c2de7fe9 + STATE: LockWaiting +WAITING_START_TIME: 2021-06-08 08:46:48.388024 + MEM_BUFFER_KEYS: 1 + MEM_BUFFER_BYTES: 19 + SESSION_ID: 87 + USER: root + DB: test + ALL_SQL_DIGESTS: [0fdc781f19da1c6078c9de7eadef8a307889c001e05f107847bee4cfc8f3cdf3, a4e28cc182bdd18288e2a34180499b9404cd0 +ba07e3cc34b6b3be7b7c2de7fe9, a4e28cc182bdd18288e2a34180499b9404cd0ba07e3cc34b6b3be7b7c2de7fe9] +*************************** 2. row *************************** + ID: 425496940994101249 + START_TIME: 2021-06-08 08:46:57.342000 +CURRENT_SQL_DIGEST: a4e28cc182bdd18288e2a34180499b9404cd0ba07e3cc34b6b3be7b7c2de7fe9 + STATE: LockWaiting +WAITING_START_TIME: 2021-06-08 08:46:57.590060 + MEM_BUFFER_KEYS: 0 + MEM_BUFFER_BYTES: 0 + SESSION_ID: 85 + USER: root + DB: test + ALL_SQL_DIGESTS: [0fdc781f19da1c6078c9de7eadef8a307889c001e05f107847bee4cfc8f3cdf3, a4e28cc182bdd18288e2a34180499b9404cd0 +ba07e3cc34b6b3be7b7c2de7fe9] +2 rows in set (0.00 sec) +``` + +#### 事务被长时间阻塞 + +如果已知一个事务被另一事务(或多个事务)阻塞,且已知当前事务的 `start_ts`(即事务 ID),则可使用如下方式获取导致该事务阻塞的事务的信息。注意对 Lock View 中的多张表进行 join 时,不同表之间的数据并不保证在同一时刻获取,因而可能不同表中的信息可能并不同步。 + +{{< copyable "sql" >}} + +```sql +select l.key, trx.* from information_schema.data_lock_waits as l join information_schema.tidb_trx as trx on l.current_holding_trx_id = trx.id where l.trx_id = 425497223886536705\G +``` + +```sql +*************************** 1. row *************************** + key: 7480000000000000475f728000000000000002 + ID: 425497219115778059 + START_TIME: 2021-06-08 09:04:38.292000 +CURRENT_SQL_DIGEST: a4e28cc182bdd18288e2a34180499b9404cd0ba07e3cc34b6b3be7b7c2de7fe9 + STATE: LockWaiting +WAITING_START_TIME: 2021-06-08 09:04:38.336264 + MEM_BUFFER_KEYS: 1 + MEM_BUFFER_BYTES: 19 + SESSION_ID: 97 + USER: root + DB: test + ALL_SQL_DIGESTS: [0fdc781f19da1c6078c9de7eadef8a307889c001e05f107847bee4cfc8f3cdf3, a4e28cc182bdd18288e2a34180499b9404cd0 +ba07e3cc34b6b3be7b7c2de7fe9, a4e28cc182bdd18288e2a34180499b9404cd0ba07e3cc34b6b3be7b7c2de7fe9] +1 row in set (0.01 sec) +``` + +如果当前事务的 `start_ts` 未知,可以尝试从 `TIDB_TRX` / `CLUSTER_TIDB_TRX` 表或者 [`PROCESSLIST` / `CLUSTER_PROCESSLIST`](/information-schema/information-schema-processlist.md) 表中的信息进行判断。