mysql 5.7 中 performance schema 无法直接监控行级锁详情,真正定位“哪一行被锁、谁在等、等多久”需依赖 information_schema.innodb_trx、innodb_lock_waits 和 innodb_locks 三张表;performance schema 仅能辅助记录 wait/innodb/innodb_lock_wait 等等待事件(需手动启用),不提供锁对象、lock_data 或事务 sql,不能替代 innodb 原生视图。

MySQL 5.7 中 Performance Schema 无法直接监控行级锁详情——它不记录行锁本身,只记录与行锁强相关的等待事件。 真正能定位“哪一行被锁、谁在等、等多久”的,是 INFORMATION_SCHEMA.INNODB_TRX、INNODB_LOCK_WAITS 和 INNODB_LOCKS 这三张表。Performance Schema 在 5.7 中仅辅助提供等待上下文(比如锁等待时长、线程堆栈),不能替代 InnoDB 层原生视图。
为什么查不到 wait/innodb/innodb_lock_wait 事件?
这是最常踩的坑:该 instrument 默认处于 DISABLED 状态,且 MySQL 5.7 的 setup_instruments 表中不包含 data_locks 或 data_lock_waits(这些是 8.0+ 才引入的)。你执行:
SELECT * FROM performance_schema.setup_instruments WHERE NAME LIKE 'wait/innodb/%lock%';
会发现 wait/innodb/innodb_lock_wait 的 ENABLED 值为 NO。
- 必须手动开启:
UPDATE performance_schema.setup_instruments SET ENABLED = 'YES' WHERE NAME = 'wait/innodb/innodb_lock_wait'; - 同时启用对应 consumer:
UPDATE performance_schema.setup_consumers SET ENABLED = 'YES' WHERE NAME = 'events_waits_history_long'; - 重启后失效,需固化到配置文件或启动时执行
如何实时抓取“谁在等谁”的阻塞链?
别依赖 Performance Schema 查阻塞关系——INNODB_LOCK_WAITS 是唯一能直接告诉你“事务 A 正在等事务 B 的哪把锁”的视图。用这个查询立刻看到当前卡住的链路:
SELECT r.trx_id waiting_trx_id, r.trx_mysql_thread_id waiting_thread, r.trx_query waiting_query,
b.trx_id blocking_trx_id, b.trx_mysql_thread_id blocking_thread, b.trx_query blocking_query,
TIMESTAMPDIFF(SECOND, r.trx_started, NOW()) wait_time_sec
FROM information_schema.INNODB_TRX r
INNER JOIN information_schema.INNODB_LOCK_WAITS w ON r.trx_id = w.requesting_trx_id
INNER JOIN information_schema.INNODB_TRX b ON b.trx_id = w.blocking_trx_id;
- 结果中
waiting_query和blocking_query可能被截断,需配合SHOW FULL PROCESSLIST补全 - 该查询只返回“已形成阻塞”的情况;瞬时竞争(如多个事务几乎同时抢同一行)捕获不到
-
wait_time_sec是事务开始时间到现在的秒数,不是锁等待实际耗时(InnoDB 不暴露该值)
怎么知道具体哪一行被锁住了?
INNODB_LOCKS 表在 MySQL 5.7 中仍可用,但字段含义易误解:LOCK_TRX_ID 是持有锁的事务 ID,LOCK_ROW_ID 并不直接等于主键值,真正能定位行的是 LOCK_DATA 字段——但它只在记录锁(record lock)下有值,间隙锁(gap lock)或临键锁(next-key lock)通常为 NULL。
- 先查
INNODB_LOCKS得到LOCK_TRX_ID和LOCK_INDEX - 再关联
INNODB_TRX查出该事务的trx_mysql_thread_id和原始 SQL - 若
LOCK_DATA非空(如123),说明锁住了主键值为 123 的行;若为空,需结合 SQL 中的 WHERE 条件和索引类型推断范围 - 注意:
INNODB_LOCKS是快照,事务提交后记录立即消失,不能用于历史回溯
Performance Schema 能做什么、不能做什么?
在 5.7 中,Performance Schema 对行锁监控的作用非常有限:
- 能做:通过
events_waits_history_long查到wait/innodb/innodb_lock_wait事件的等待时长、调用堆栈、线程 ID,辅助判断锁等待是否高频或集中在某类操作 - 不能做:不提供锁对象(表、索引、行)、不暴露
LOCK_DATA、不关联事务 SQL、不支持锁粒度聚合统计 - 性能影响:开启
wait/innodb/innodb_lock_wait后,每个锁等待都会触发一次 instrument 记录,高并发下可能轻微增加开销,但远低于慢查询日志 - 别混淆
metadata_locks:那是元数据锁(MDL),和 DDL 操作相关,与行级锁无关
真正要定位行级锁,必须回到 InnoDB 原生视图组合查询;Performance Schema 在 5.7 中只是补充,不是主力。











