Skip to content

Commit

Permalink
Add Lock View related documents (#6408)
Browse files Browse the repository at this point in the history
  • Loading branch information
MyonKeminta authored Jun 15, 2021
1 parent 5f4b573 commit 56793a8
Show file tree
Hide file tree
Showing 7 changed files with 580 additions and 2 deletions.
3 changes: 3 additions & 0 deletions TOC.md
Original file line number Diff line number Diff line change
Expand Up @@ -423,7 +423,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)
Expand All @@ -444,6 +446,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)
Expand Down
86 changes: 86 additions & 0 deletions information-schema/information-schema-data-lock-waits.md
Original file line number Diff line number Diff line change
@@ -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)
196 changes: 196 additions & 0 deletions information-schema/information-schema-deadlocks.md
Original file line number Diff line number Diff line change
@@ -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)
Loading

0 comments on commit 56793a8

Please sign in to comment.