performance_schema是常驻内存的性能监控框架,非嵌套引擎;需启用events_waits消费者和wait/lock仪器,通过data_locks与data_lock_waits表关联innodb_trx,还原锁等待链及事务上下文。

MySQL 的 performance_schema 本身不是“嵌套内存引擎”,它是一个**常驻内存的性能监控框架**,不存储业务数据,也不参与事务或锁的执行逻辑。所谓“深度诊断死锁根源”,关键在于正确启用、查询其锁相关表,并结合上下文还原等待链与事务行为——而不是依赖某种虚构的嵌套机制。
确认 performance_schema 已启用并配置锁监控
默认情况下,performance_schema 是开启的,但锁相关的事件采集器(consumers)可能被禁用:
- 检查是否启用等待事件采集:
SELECT * FROM performance_schema.setup_consumers WHERE NAME LIKE 'events_waits%';
确保events_waits_current、events_waits_history_long等状态为 YES - 启用锁相关仪器(instruments):
UPDATE performance_schema.setup_instruments SET ENABLED = 'YES', TIMED = 'YES' WHERE NAME LIKE 'wait/lock%'; - 重启后生效(部分配置需重启实例),或动态生效(取决于 MySQL 版本和参数)
核心查询:定位实时锁等待与持有关系
在 MySQL 8.0+ 中,INNODB_LOCKS 和 INNODB_LOCK_WAITS 已移除,必须使用以下两张表构建完整视图:
-
performance_schema.data_locks:列出当前所有事务持有的锁(类型、索引名、锁定记录或范围、事务 ID) -
performance_schema.data_lock_waits:显示“谁在等谁”的等待关系,含等待事务 ID(REQUESTING_ENGINE_TRANSACTION_ID)和阻塞事务 ID(BLOCKING_ENGINE_TRANSACTION_ID) - 典型关联查询示例:
SELECT r.trx_id AS waiting_trx, r.trx_query AS waiting_sql, b.trx_id AS blocking_trx, b.trx_query AS blocking_sql FROM performance_schema.data_lock_waits w JOIN information_schema.INNODB_TRX r ON w.REQUESTING_ENGINE_TRANSACTION_ID = r.trx_id JOIN information_schema.INNODB_TRX b ON w.BLOCKING_ENGINE_TRANSACTION_ID = b.trx_id;
结合事务状态还原执行上下文
仅看锁不够,必须把锁和正在运行的事务对齐:
- 查活跃事务:
SELECT trx_id, trx_state, trx_started, trx_mysql_thread_id, trx_query FROM information_schema.INNODB_TRX ORDER BY trx_started DESC LIMIT 10;
重点关注trx_state = 'LOCK WAIT'的事务,再通过 thread_id 关联到 processlist 或应用日志 - 查线程信息:
SELECT * FROM performance_schema.threads WHERE PROCESSLIST_ID = ?;
可获取该线程的用户、数据库、命令类型,辅助判断是哪类应用请求 - 若需追溯 SQL 执行堆栈(如触发锁的完整调用路径),需提前开启
events_statements_history_long并关联EVENT_ID,但开销较大,建议按需临时启用
避免常见误操作
很多排查失败源于对机制理解偏差:
- 不要试图从
data_locks表直接读出“死锁”——它只反映**当前锁状态**,死锁是瞬时检测结果,已回滚的事务锁会被清理 -
data_lock_waits不是历史记录表,它只保留**当前正在等待**的关系;死锁发生后,等待关系已被 InnoDB 清除,只剩错误日志和SHOW ENGINE INNODB STATUS的快照 - 未开启
innodb_print_all_deadlocks=ON时,错误日志里只会记录最后一次死锁;高频场景务必开启,否则无法回溯 - performance_schema 的锁信息不含 SQL 文本,
trx_query来自INNODB_TRX,二者需 JOIN 使用,不能只查一张表就下结论











