MySQL 8.0锁监控必须用SET GLOBAL innodb_status_output_locks = ON动态开启,重启失效;输出每15秒追加至错误日志的TRANSACTIONS和LOCK WAIT段,仅当真实锁等待发生时才显示WAITING记录。

MySQL 8.0 的锁监控不能靠配置文件直接开启,必须用 SET GLOBAL 动态设置,且仅对当前实例生效;重启后失效,不加持久化配置等于白开。
确认 MySQL 版本并选择对应变量名
MySQL 5.6.16 起废弃了 innodb_lock_monitor,改用 innodb_status_output_locks。8.0 默认使用该变量,但必须显式设为 ON 才生效:
- 执行
SELECT VERSION();确认是8.0.x(不是 5.7 或更早) - 运行
SHOW VARIABLES LIKE 'innodb_status_output_locks';,若返回OFF或不存在,说明未启用 - 必须用
SET GLOBAL innodb_status_output_locks = ON;开启 —— 直接写进my.cnf在旧版本会报错,在 8.0 中虽支持但需重启才加载,不如动态设置即时生效
锁信息实际输出到哪?怎么看
启用后,InnoDB 每 15 秒自动调用 SHOW ENGINE INNODB STATUS 并把完整输出追加到错误日志(log_error 指定的文件),不是慢日志、不是 general log,也不是 stdout。
- 先查错误日志路径:
SELECT @@global.log_error;,常见如/var/log/mysql/error.log或/data/3306/log/mysql-err.log - 锁详情集中在输出里的
TRANSACTIONS和LOCK WAIT段 —— 注意不是每次都有WAITING记录,只有真实发生锁等待时才会出现 - 典型线索包括:
WAITING FOR THIS LOCK TO BE GRANTED、HELD LOCKS、RECORD LOCKS space id X page no Y - 如果日志里只看到
INNODB MONITOR OUTPUT头部但没锁细节,说明变量没生效或当前无锁争用
为什么开了却看不到 WAITING 记录
这是最常被误解的一点:锁监控输出的是“快照”,不是实时流。它只在有活跃锁等待时才展示阻塞关系,否则只显示事务和持有锁列表。
-
innodb_status_output_locks = ON后,必须有至少两个事务在互相等待(比如一个 UPDATE 行 A,另一个 UPDATE 行 A),才能触发LOCK WAIT段落 - 单纯执行
SELECT ... FOR UPDATE但没并发冲突,不会产生WAITING行 - 错误日志权限问题也会导致写入失败:确保 MySQL 进程对
log_error文件路径有写权限,否则 silently 丢弃输出 - 如果用
log_error_services自定义了日志组件(比如只留log_sink_json),默认文本格式的 monitor 输出可能被过滤掉
如何验证监控真正在工作
别只信 SHOW VARIABLES 返回 ON,要看到真实日志内容才算数。
- 手动制造一次锁等待:开两个会话,Session A 执行
BEGIN; UPDATE t SET v=1 WHERE id=1;不提交;Session B 执行相同语句 —— 此时立刻查错误日志,应能在最近 15 秒内看到新增的LOCK WAIT块 - 检查日志时间戳是否连续:每 15 秒应有一段以
INNODB MONITOR OUTPUT开头的块,包含SEMAPHORES、TRANSACTIONS等节 - 注意性能影响:该监控会增加 CPU 和 I/O,长期开启需评估 —— 它不改变锁行为,但日志体积会明显上涨,尤其高并发场景
真正难的不是打开开关,而是读懂 TRANSACTIONS 段里那一长串十六进制 trx_id、space id 和 n bits 字段所对应的行键值;这些信息不带表名字段名,全靠你反向解析 page no 和 index info,稍不留神就定位错行。


















