MySQL 8.0.15+ 应查 performance_schema.data_locks 定位行锁,关键字段 LOCK_DATA 显示被锁行的主键或索引值(如12、'user_100'),配合 LOCK_TYPE='RECORD' 和 LOCK_MODE 确认行锁;需结合 data_lock_waits 和 INNODB_TRX 关联事务与会话,才能完整追踪阻塞源头及可操作线程ID。

查 performance_schema.data_locks 定位具体行锁记录
MySQL 8.0.15+ 推荐用 performance_schema.data_locks 替代已弃用的 INNODB_LOCKS,它能精确展示锁类型、锁对象(包括主键值或索引值)和事务 ID。关键字段是 LOCK_DATA,它会显示被锁行的索引列值(如 12、'user_100'),配合 LOCK_MODE 和 LOCK_TYPE='RECORD' 可确认是行锁。
要追踪某一行(比如 id = 12),直接查:
SELECT ENGINE_TRANSACTION_ID, LOCK_TRX_ID, LOCK_MODE, LOCK_TYPE, LOCK_TABLE, LOCK_INDEX, LOCK_DATA FROM performance_schema.data_locks WHERE LOCK_TYPE = 'RECORD' AND LOCK_DATA LIKE '%12%';
注意:LOCK_DATA 是字符串形式,不保证格式统一;若表有联合索引,它可能显示多个值拼接(如 12, 'ACTIVE'),需结合 LOCK_INDEX 判断是否匹配目标索引。
用 LOCK_TRX_ID 关联 performance_schema.data_lock_waits 找阻塞源头
data_locks 只告诉你“谁持有了锁”,但不说明“谁在等它”。真正要定位“为什么卡住”,得看 data_lock_waits 中的等待关系。它的 BLOCKING_ENGINE_TRANSACTION_ID 字段指向持锁事务的内部 ID,正好和 data_locks.ENGINE_TRANSACTION_ID 对应。
常用组合查询(一次拿到持锁者 + 等待者):
面向 CRM 系统的 MySQL 8 数据库模式设计。当用户需要为客户关系管理(CRM)系统设计、评审、优化或生成数据库模式时,应使用此项技能。
SELECT w.BLOCKING_ENGINE_TRANSACTION_ID AS blocking_trx_id, w.REQUESTING_ENGINE_TRANSACTION_ID AS waiting_trx_id, l.LOCK_DATA, l.LOCK_MODE, l.LOCK_TABLE FROM performance_schema.data_lock_waits w JOIN performance_schema.data_locks l ON w.BLOCKING_ENGINE_TRANSACTION_ID = l.ENGINE_TRANSACTION_ID WHERE l.LOCK_DATA LIKE '%12%';
这个结果里没有用户会话信息——只是事务级 ID,下一步才需要映射到线程。
通过 sys.processlist 把事务 ID 转成可操作的会话
ENGINE_TRANSACTION_ID 是 InnoDB 内部 ID,不能直接 kill;必须转成 processlist.id 才能执行 KILL。转换链路是:data_locks.ENGINE_TRANSACTION_ID → INNODB_TRX.trx_id → INNODB_TRX.trx_mysql_thread_id → sys.processlist.id。
推荐用 sys 库视图一步到位(兼容性好、字段语义清晰):
SELECT pl.ID AS thread_id, pl.USER, pl.HOST, pl.DB, pl.INFO AS current_sql, trx.trx_started, trx.trx_state FROM performance_schema.data_locks l JOIN information_schema.INNODB_TRX trx ON l.LOCK_TRX_ID = trx.trx_id JOIN sys.processlist pl ON trx.trx_mysql_thread_id = pl.id WHERE l.LOCK_DATA LIKE '%12%' AND l.LOCK_TYPE = 'RECORD';
- 若
pl.INFO为空,说明事务空闲或刚提交,重点看trx_started和trx_state - 若查不到结果,可能是权限不足(需
PROCESS+SELECTonperformance_schema)、事务已结束、或该锁由内部线程(如 DDL)持有 -
sys.processlist默认过滤掉Daemon和Background线程,这类持锁者不会出现
为什么有时 LOCK_DATA 查不到对应值?
不是所有行锁都会在 LOCK_DATA 显式写出主键值。常见原因:
- 锁在二级索引上,而
LOCK_DATA显示的是该索引字段值(比如你查id=12,但它实际锁的是email索引,值可能是'test@ex.com') - 间隙锁(Gap Lock)或临键锁(Next-key Lock)不锁定具体记录,
LOCK_DATA可能为NULL或只显示范围(如10, 15) - 使用了覆盖索引,InnoDB 可能只锁索引页而不锁主键,导致
LOCK_DATA不包含主键列 - 表无主键或唯一索引时,InnoDB 用隐式聚簇索引,
LOCK_DATA显示的是内部ROW_ID,不可读
这时候得退回到 SHOW ENGINE INNODB STATUS\G 的 TRANSACTIONS 部分手动比对,或者检查 SQL 是否命中了预期索引(用 EXPLAIN)。行锁的“具体哪一行”从来不是绝对确定的,它取决于执行计划和索引结构。

















