performance schema 默认不开启任何锁监控事件,需手动启用 wait/lock% 类型的 instruments 和 eventswaits* 消费者;否则 data_locks 等表为空,并非无锁而是未采集。

Performance Schema 默认开启哪些锁监控事件?
默认情况下,performance_schema 并不自动采集锁相关事件。必须手动启用对应消费者(consumer)和仪器(instrument),否则 data_locks、data_lock_waits 等表始终为空。
常见误判是查了 SELECT * FROM performance_schema.data_locks 返回空,就以为“没锁”,其实是没开采集。真正生效需两步:
- 确认
performance_schema已启用:SHOW VARIABLES LIKE 'performance_schema';必须为ON - 启用锁事件采集:
UPDATE performance_schema.setup_instruments SET ENABLED = 'YES', TIMED = 'YES' WHERE NAME LIKE 'wait/lock%'; - 启用对应消费者:
UPDATE performance_schema.setup_consumers SET ENABLED = 'YES' WHERE NAME IN ('events_waits_current', 'events_waits_history', 'events_waits_history_long');
注意:setup_instruments 修改仅对新连接生效;已有连接的会话不会自动加载新 instrument,需重连或重启会话。
为什么频繁查询 data_locks 会导致性能下降?
performance_schema.data_locks 是实时快照视图,每次查询都会触发 InnoDB 内核遍历所有事务持有的锁结构,生成当前锁状态。在高并发写入场景下,这个操作本身会争用 trx_sys->mutex,造成明显延迟。
典型现象包括:
- 执行
SELECT * FROM performance_schema.data_locks耗时突然从几毫秒飙升到 200ms+ - 伴随
innodb_mutex_spin_waits值异常升高 - 其他正常 SQL 出现偶发性卡顿,但慢日志里找不到对应慢语句
这不是锁本身的问题,而是监控行为反成瓶颈。所以不能“想看就查”,得控制频率和范围。
如何安全地降低锁监控开销?
核心思路是:只采集必要事件 + 限制采集深度 + 避免全量轮询。
- 禁用非关键锁 instrument:
UPDATE performance_schema.setup_instruments SET ENABLED = 'NO' WHERE NAME IN ('wait/lock/metadata/sql/mdl', 'wait/lock/table/sql/handler');(元数据锁和表级锁通常不是性能瓶颈主因) - 限制历史长度:设
performance_schema_events_waits_history_long_size = 10000(默认 15000),避免内存堆积 - 查锁时不扫全表:
SELECT * FROM performance_schema.data_locks WHERE LOCK_TRX_ID IN (SELECT TRX_ID FROM information_schema.INNODB_TRX WHERE TIME_TO_SEC(NOW() - TRX_STARTED) > 10);只查运行超 10 秒的事务锁 - 用
sys.schema_table_lock_waits替代裸查data_locks:它已预过滤,且加了索引提示,响应更快
这些调整后,锁监控 CPU 占比可从 8%–12% 降至 1% 以内,且不影响关键冲突定位能力。
什么时候该关掉锁监控?
不是所有环境都需要锁监控常开。以下情况建议关闭锁相关 instrument:
- 生产库已稳定运行半年以上,
innodb_row_lock_waits持续为 0,且无死锁报警 - 实例部署在资源受限的边缘节点(如 2 核 4GB),
performance_schema总内存占用已超 300MB - 使用了外部 APM(如 Datadog、SkyWalking)做分布式事务追踪,锁等待已通过 span 标签捕获
关锁监控不是“放弃可观测性”,而是把资源让给更关键的指标——比如 events_statements_summary_by_digest 或 buffer pool 命中率。真实线上问题里,90% 的锁等待其实靠 SHOW ENGINE INNODB STATUS + 慢日志就能闭环,不需要实时 data_locks。











