mysql 8.0+ 中应使用 show status like 'innodb_row_lock_current_waits' 初筛锁等待,再通过 performance_schema.data_lock_waits 关联 innodb_trx 定位阻塞详情并计算等待时长,而非依赖已废弃的 innodb_lock_waits 表。

MySQL 8.0+ 中无法靠 INNODB_LOCK_WAITS 表实时监控锁等待时间,它已为空且不反映当前状态;真正可用的是 performance_schema.data_lock_waits 配合 INNODB_TRX 计算等待时长。
查当前有没有锁等待(最快初筛)
别一上来就 join 多张表,先用低开销命令确认是否存在等待:
- 执行
SHOW STATUS LIKE 'innodb_row_lock_current_waits';—— 返回值 > 0 表示此刻有事务卡在行锁上 - 搭配看
innodb_row_lock_time_avg:若该值突然从毫秒级跳到几十毫秒以上,说明等待已成规模,不是偶发抖动 - 这个状态变量权限要求低、响应快,普通账号也能查,适合线上高频轮询
- 注意:它归零不代表问题消失——可能只是锁刚释放,或等待刚好超时(默认
innodb_lock_wait_timeout=50秒)
定位谁在等、谁在挡(MySQL 8.0+ 正确关联方式)
必须用 performance_schema.data_lock_waits,但默认不采集,得先开开关:
- 检查锁相关 instrument 是否启用:
SELECT NAME, ENABLED FROM performance_schema.setup_instruments WHERE NAME LIKE 'wait/lock/%';,确保wait/lock/innoDB/lock等项为YES - 打开消费者:
UPDATE performance_schema.setup_consumers SET ENABLED = 'YES' WHERE NAME IN ('global_instrumentation', 'thread_instrumentation'); - 关键查询(注意字段类型匹配):
SELECT r.trx_id waiting_trx_id, r.trx_mysql_thread_id waiting_pid, r.trx_query waiting_query, b.trx_id blocking_trx_id, b.trx_mysql_thread_id blocking_pid, b.trx_query blocking_query FROM performance_schema.data_lock_waits w JOIN information_schema.INNODB_TRX b ON b.trx_id = w.BLOCKING_ENGINE_TRANSACTION_ID JOIN information_schema.INNODB_TRX r ON r.trx_id = w.REQUESTING_ENGINE_TRANSACTION_ID; - 踩坑点:
BLOCKING_ENGINE_TRANSACTION_ID必须连INNODB_TRX.trx_id,不能误连trx_mysql_thread_id(后者是线程 ID,类型不一致,查不到结果)
计算“当前等待时长”并用于告警(实操关键)
仅知道谁在等不够,要量化影响,就得算等待了多久:
- 从
INNODB_TRX表中取trx_wait_started字段(MySQL 5.7+ 支持),再用NOW() - trx_wait_started得到秒级等待时长 - 不要直接把
trx_query当 Prometheus 标签上报——SQL 长度不可控、基数爆炸,会撑爆内存;改用哈希(如MURMUR3(trx_query))生成query_hash标签 - 监控指标建议:
mysql_innodb_trx_wait_seconds(Gauge 类型,实时值)、mysql_innodb_lock_waits_total(Counter 类型,每分钟采一次COUNT(*) FROM performance_schema.data_lock_waits) - 告警阈值参考:等待 > 5 秒触发 warning,> 15 秒触发 critical——业务能容忍的等待时间因场景而异,需结合
innodb_lock_wait_timeout设置反推
为什么 SHOW ENGINE INNODB STATUS 不能当实时监控用?
它输出的是 15 秒一次的快照,且只保留最近一次死锁和部分活跃事务信息:
- 锁等待详情只出现在 “TRANSACTIONS” 和 “LOCK WAIT” 段落中,但必须有真实等待发生才会写入,空闲时无内容
- 日志位置固定在 MySQL 错误日志(
error_log),不是 slow log 或 general log - 启用
innodb_status_output_locks = ON后,每 15 秒自动追加完整输出,但无法按事务粒度提取结构化数据,不适合自动化解析 - 它适合人工排查,不适合写进监控脚本——你没法保证每次
grep都能抓到刚发生的等待
真正稳定的实时监控必须依赖 performance_schema 的结构化表 + 时间戳计算,而不是依赖瞬时快照或已废弃的视图。最容易被忽略的是 data_lock_waits 的采集开关和字段类型匹配,这两步漏掉,查出来永远是空结果。











