MySQL 5.7+ 锁等待信息只能从 performance_schema 获取,关键表为 data_locks、data_lock_waits 和 events_waits_summary_global_by_event_name,需启用对应配置并用 mysqld_exporter 配合 --collect.perf_schema.eventswaits 等参数采集。

查哪些表能拿到MySQL锁等待信息
MySQL 5.7+ 的 performance_schema 是唯一实时、低开销的锁监控来源,information_schema.INNODB_TRX 和 INNODB_LOCK_WAITS 已被弃用且不准确——它们只反映快照,无法捕获瞬时锁争用。
必须开启以下配置,否则相关表为空:
-
performance_schema=ON(默认通常已开) performance_schema_events_waits_history_long_enabled=ONperformance_schema_mutex_classes_enabled=ONperformance_schema_rwlock_classes_enabled=ON
关键表是:performance_schema.data_locks(当前持有/等待的行级锁)、performance_schema.data_lock_waits(显式锁等待链)、performance_schema.events_waits_summary_global_by_event_name(按事件类型统计等待总时长)。
用mysqld_exporter暴露锁指标给Prometheus
官方 mysqld_exporter 默认不采集锁相关指标,因为开销敏感——它只拉取 information_schema 和状态变量,而锁数据在 performance_schema 中,需手动启用。
启动时加参数才能抓到锁等待数和平均等待时间:
-
--collect.perf_schema.eventswaits:启用等待事件汇总(含锁等待) -
--collect.perf_schema.data_locks:启用行锁详情(会显著增加内存和查询负载,生产慎用) - 推荐组合:
--collect.perf_schema.eventswaits --collect.info_schema.innodb_metrics
示例命令:
./mysqld_exporter --config.my-cnf=.my.cnf --collect.perf_schema.eventswaits --web.listen-address=:9104
之后在 Prometheus 中可查:mysql_perf_schema_events_waits_total{event_name=~"wait/synch/mutex/innodb/.*|wait/lock/.*"} 或按 operation 标签区分 lock_wait 类型。
避免误读“锁等待次数”指标
mysql_perf_schema_events_waits_total 统计的是所有等待事件,不是“死锁次数”或“阻塞事务数”。常见误解:
- 该指标包含自旋锁、信号量、MDL锁、InnoDB行锁等全部同步等待,不能直接等同于业务阻塞
- 高值未必代表问题——比如批量导入时
wait/synch/mutex/innodb/buf_pool_mutex上升属正常 - 真正要盯的是
wait/lock/table/sql/handler(MDL锁)和wait/lock/innodb/row_lock(行锁)这两类,且需结合avg_time看延迟是否突增
建议搭配告警规则:
rate(mysql_perf_schema_events_waits_total{event_name=~"wait/lock/innodb/row_lock|wait/lock/table/sql/handler"}[5m]) > 100
再叠加 mysql_perf_schema_events_waits_average_time_ms{...} > 50 才有实际意义。
为什么不用SHOW ENGINE INNODB STATUS解析锁信息
虽然 SHOW ENGINE INNODB STATUS 能看到当前锁等待图,但它是一次性文本输出,无法被 Prometheus 直接采集,也不支持按标签维度聚合。更关键的是:
- 输出内容无结构化字段,解析极易出错(如换行、缩进、字段缺失)
- 每执行一次都会触发内部扫描,QPS 高时可能拖慢 InnoDB
- 结果只保留最近一次死锁信息,对持续性锁争用无感知
- Prometheus 生态中没有稳定可靠的 exporter 做这事,硬写解析器等于重复造轮子
真要调试具体锁冲突,就登录 MySQL 手动跑:SELECT * FROM performance_schema.data_lock_waits; + 关联 data_locks 查事务和SQL,别指望靠指标曲线定位到某条UPDATE语句。











