- 关于 TiDB
- 快速上手
- 部署标准集群
- 数据迁移
- 运维操作
- 监控与告警
- 故障诊断
- 性能调优
- 系统调优
- 软件调优
- SQL 性能调优
- SQL 性能调优概览
- 理解 TiDB 执行计划
- SQL 优化流程
- 控制执行计划
- 教程
- TiDB 工具
- 功能概览
- 适用场景
- 工具下载
- TiUP
- TiDB Operator
- Dumpling
- TiDB Lightning
- TiDB Data Migration
- Backup & Restore (BR)
- TiDB Binlog
- TiCDC
- sync-diff-inspector
- TiSpark
- 参考指南
- 架构
- 监控指标
- 安全加固
- 权限
- SQL
- SQL 语言结构和语法
- SQL 语句
ADD COLUMN
ADD INDEX
ADMIN
ADMIN CANCEL DDL
ADMIN CHECKSUM TABLE
ADMIN CHECK [TABLE|INDEX]
ADMIN SHOW DDL [JOBS|QUERIES]
ALTER DATABASE
ALTER INDEX
ALTER INSTANCE
ALTER TABLE
ALTER USER
ANALYZE TABLE
BACKUP
BEGIN
CHANGE COLUMN
CHANGE DRAINER
CHANGE PUMP
COMMIT
CREATE [GLOBAL|SESSION] BINDING
CREATE DATABASE
CREATE INDEX
CREATE ROLE
CREATE SEQUENCE
CREATE TABLE LIKE
CREATE TABLE
CREATE USER
CREATE VIEW
DEALLOCATE
DELETE
DESC
DESCRIBE
DO
DROP [GLOBAL|SESSION] BINDING
DROP COLUMN
DROP DATABASE
DROP INDEX
DROP ROLE
DROP SEQUENCE
DROP STATS
DROP TABLE
DROP USER
DROP VIEW
EXECUTE
EXPLAIN ANALYZE
EXPLAIN
FLASHBACK TABLE
FLUSH PRIVILEGES
FLUSH STATUS
FLUSH TABLES
GRANT <privileges>
GRANT <role>
INSERT
KILL [TIDB]
LOAD DATA
LOAD STATS
MODIFY COLUMN
PREPARE
RECOVER TABLE
RENAME INDEX
RENAME TABLE
REPLACE
RESTORE
REVOKE <privileges>
REVOKE <role>
ROLLBACK
SELECT
SET DEFAULT ROLE
SET [NAMES|CHARACTER SET]
SET PASSWORD
SET ROLE
SET TRANSACTION
SET [GLOBAL|SESSION] <variable>
SHOW [BACKUPS|RESTORES]
SHOW ANALYZE STATUS
SHOW [GLOBAL|SESSION] BINDINGS
SHOW BUILTINS
SHOW CHARACTER SET
SHOW COLLATION
SHOW [FULL] COLUMNS FROM
SHOW CONFIG
SHOW CREATE SEQUENCE
SHOW CREATE TABLE
SHOW CREATE USER
SHOW DATABASES
SHOW DRAINER STATUS
SHOW ENGINES
SHOW ERRORS
SHOW [FULL] FIELDS FROM
SHOW GRANTS
SHOW INDEX [FROM|IN]
SHOW INDEXES [FROM|IN]
SHOW KEYS [FROM|IN]
SHOW MASTER STATUS
SHOW PLUGINS
SHOW PRIVILEGES
SHOW [FULL] PROCESSSLIST
SHOW PROFILES
SHOW PUMP STATUS
SHOW SCHEMAS
SHOW STATS_HEALTHY
SHOW STATS_HISTOGRAMS
SHOW STATS_META
SHOW STATUS
SHOW TABLE NEXT_ROW_ID
SHOW TABLE REGIONS
SHOW TABLE STATUS
SHOW [FULL] TABLES
SHOW [GLOBAL|SESSION] VARIABLES
SHOW WARNINGS
SHUTDOWN
SPLIT REGION
START TRANSACTION
TABLE
TRACE
TRUNCATE
UPDATE
USE
WITH
- 数据类型
- 函数与操作符
- 聚簇索引
- 约束
- 生成列
- SQL 模式
- 事务
- 垃圾回收 (GC)
- 视图
- 分区表
- 字符集和排序规则
- 系统表
mysql
- INFORMATION_SCHEMA
- Overview
ANALYZE_STATUS
CLIENT_ERRORS_SUMMARY_BY_HOST
CLIENT_ERRORS_SUMMARY_BY_USER
CLIENT_ERRORS_SUMMARY_GLOBAL
CHARACTER_SETS
CLUSTER_CONFIG
CLUSTER_HARDWARE
CLUSTER_INFO
CLUSTER_LOAD
CLUSTER_LOG
CLUSTER_SYSTEMINFO
COLLATIONS
COLLATION_CHARACTER_SET_APPLICABILITY
COLUMNS
DATA_LOCK_WAITS
DDL_JOBS
DEADLOCKS
ENGINES
INSPECTION_RESULT
INSPECTION_RULES
INSPECTION_SUMMARY
KEY_COLUMN_USAGE
METRICS_SUMMARY
METRICS_TABLES
PARTITIONS
PROCESSLIST
SCHEMATA
SEQUENCES
SESSION_VARIABLES
SLOW_QUERY
STATISTICS
TABLES
TABLE_CONSTRAINTS
TABLE_STORAGE_STATS
TIDB_HOT_REGIONS
TIDB_INDEXES
TIDB_SERVERS_INFO
TIDB_TRX
TIFLASH_REPLICA
TIKV_REGION_PEERS
TIKV_REGION_STATUS
TIKV_STORE_STATUS
USER_PRIVILEGES
VIEWS
METRICS_SCHEMA
- UI
- CLI
- 命令行参数
- 配置文件参数
- 系统变量
- 存储引擎
- 遥测
- 错误码
- 通过拓扑 label 进行副本调度
- 常见问题解答 (FAQ)
- 版本发布历史
- 发布版本汇总
- v5.1
- v5.0
- v4.0
- v3.1
- v3.0
- v2.1
- v2.0
- v1.0
- 术语表
DEADLOCKS
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 | |
| 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
配置项进行调整,默认容纳最近 10 次死锁错误的信息。
示例 1
假设有如下表定义和初始数据:
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
表,将得到如下结果:
select * from information_schema.deadlocks;
+-------------+----------------------------+-----------+--------------------+------------------------------------------------------------------+----------------------------------------+--------------------+
| 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
表得到了如下结果集:
+-------------+----------------------------+-----------+--------------------+------------------------------------------------------------------+----------------------------------------+--------------------+
| 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 开始后到被阻塞前这段时间内已经执行完成的语句产生的锁阻塞
- 情况二:事务 B 也可能被事务 A 目前正在执行的语句阻塞
对于情况一,TiDB 将会向事务 A 的客户端报告死锁错误,并终止该事务;而对于情况二,事务 A 当前正在执行的语句将在 TiDB 内部被自动重试。例如,假设事务 A 执行了如下语句:
update t set v = v + 1 where id = 1 or id = 2;
事务 B 则先后执行如下两条语句:
update t set v = 4 where id = 2;
update t set v = 2 where id = 1;
那么如果事务 A 先后对 id = 1
和 id = 2
的两行分别上锁,且两个事务以如下时序运行:
- 事务 A 对
id = 1
的行上锁 - 事务 B 执行第一条语句并对
id = 2
的行上锁 - 事务 B 执行第二条语句试图对
id = 1
的行上锁,被事务 A 阻塞 - 事务 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
两个字段共同区分结果集中的不同死锁错误的信息。
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 | |
| 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 原文。
select digest, digest_text from information_schema.statements_summary where digest = "f7530877a35ae65300c42250abd8bc731bbaf0a7cabc05dab843565230611bb2";
+------------------------------------------------------------------+---------------------------------------+
| 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。