查performance_schema.data_locks是唯一能精确到行级的途径:该表在MySQL 8.0+中替代已移除的INNODB_LOCKS,通过LOCK_DATA字段直接显示被锁行的主键或索引值,结合OBJECT_NAME、INDEX_NAME、LOCK_TYPE等字段可精确定位具体锁定记录。

查 performance_schema.data_locks 是唯一能精确到行级的途径
MySQL 8.0+ 中,INFORMATION_SCHEMA.INNODB_LOCKS 已被移除,sys.innodb_lock_waits 只告诉你“谁在等、等谁”,但不告诉你“锁了哪几行”。真正能列出具体锁定的索引记录(包括主键值、间隙范围)的,只有 performance_schema.data_locks。
它每条记录对应一个锁实例,关键字段有:OBJECT_NAME(表名)、INDEX_NAME(索引名)、LOCK_TYPE(RECORD 表示行锁)、LOCK_MODE(如 X,REC_NOT_GAP)、LOCK_DATA(被锁的具体索引值,例如 123 或 50, 'abc')。
- 执行
SELECT * FROM performance_schema.data_locks WHERE LOCK_TRX_ID = 'xxx';,其中xxx来自INFORMATION_SCHEMA.INNODB_TRX.trx_id,就能看到该事务持有的所有锁 -
LOCK_DATA是核心——如果是主键或唯一索引,通常显示具体值;如果是二级索引+间隙锁,可能显示类似100, 'xyz', supremum pseudo-record - 注意:默认
performance_schema可能未启用相关消费者,需确认setup_consumers中events_transactions_current和data_locks为YES
LOCK_DATA 字段值怎么看懂
LOCK_DATA 不是 SQL 表达式,而是 InnoDB 内部索引项的序列化表示,直接反映加锁位置。常见模式:
- 单列主键:显示纯数值,如
456→ 锁住主键值为 456 的那行 - 联合主键:用逗号分隔,如
1, 'user_001'→ 对应(id, username)索引中该组合值 - 间隙锁(GAP):含
supremum pseudo-record或infimum pseudo-record→ 表示锁住索引区间,比如(100, 200)之间的空隙 - next-key 锁(默认):同时含记录值 + gap,如
100, 'a', supremum pseudo-record→ 锁住值为 100 的行及其右侧间隙
别指望它显示业务字段名,它只展示索引结构里的实际存储值。想映射回业务数据,得结合 INDEX_NAME 和表定义反推。
为什么 INNODB_TRX 和 SHOW ENGINE INNODB STATUS 都不够细
INFORMATION_SCHEMA.INNODB_TRX 只告诉你事务存在、状态、SQL 和大致锁行数(trx_rows_locked),但这个数字是估算值,且不区分行、页、间隙;SHOW ENGINE INNODB STATUS 的 TRANSACTIONS 部分虽会列出“lock_mode X locks rec but not gap on table_name”,但不会输出 LOCK_DATA,更不会告诉你具体是哪几行。
-
trx_rows_locked字段常严重失真:插入时可能报 0,大范围 UPDATE 却只报几十——它基于锁结构计数,不是真实扫描行数 -
SHOW ENGINE INNODB STATUS中的 lock info 是文本快照,解析困难,且只保留最近几个事务,无法关联到特定trx_id - 若事务已提交或回滚,
data_locks里对应记录立即消失,必须在锁持有期间查
容易忽略的权限和配置陷阱
即使你用的是 MySQL 8.0+,performance_schema.data_locks 默认也可能查不到数据——不是 bug,是权限或配置关了。
- 用户必须有
SELECT权限在performance_schema库,且需额外被授予PROCESS权限(否则只能看到自己的锁) - 检查
performance_schema是否启用:运行SELECT VARIABLE_VALUE FROM performance_schema.global_variables WHERE VARIABLE_NAME = 'performance_schema';,结果必须为ON - 关键消费者是否开启:
SELECT * FROM performance_schema.setup_consumers WHERE NAME LIKE '%data%';,确保data_locks行的ENABLED是YES - 某些云数据库(如阿里云 RDS)默认关闭
data_locks,需在控制台手动开启或提工单
没开 data_locks 消费者时,表返回空,不是没锁,是根本没采集——这点最容易误判为“没锁问题”。


















