Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add Lock View related documents #6408

Merged
merged 15 commits into from
Jun 15, 2021
3 changes: 3 additions & 0 deletions TOC.md
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand All @@ -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)
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,以十六进制编码的形式显示。
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

tidb 现在有办法能解析这种 key 是哪个表哪一行或者索引吗?没有的话下个 sprint 要优化一下体验,可能用户知道了 sql 也没用,还要知道是哪一行才行。

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

这个后续迭代可以考虑再加个字段展示把 key 解出来的信息。目前可能得借助些其它的工具才能解。我等会看下 tidb-ctl 顶用不顶用,能用的话晚点我把它补充进文档里。

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

tidb-ctl 好像不行...

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

* `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` 的事务持有。
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.


## 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`。
TomShawn marked this conversation as resolved.
Show resolved Hide resolved
* `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 直接或间接地被当前事务持有的锁阻塞,将会引发一个死锁错误。这里:
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.


+ 情况一:事务 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