查锁优先用 information_schema.innodb_trx,适合程序化采集并可关联 processlist 获取sql;show engine innodb status 仅用于人工排查阻塞链,因输出非结构化需正则解析且不稳定。

查锁用 INFORMATION_SCHEMA.INNODB_TRX 还是 SHOW ENGINE INNODB STATUS
前者适合程序化采集,后者能看实时阻塞链但输出非结构化。INFORMATION_SCHEMA.INNODB_TRX 返回每条事务的 trx_state、trx_started、trx_wait_started 和 trx_mysql_thread_id,可直接 JOIN PROCESSLIST 获取 SQL 文本;而 SHOW ENGINE INNODB STATUS 的 TRANSACTIONS 部分里有 lock struct(s) 和 waiting for this lock to be granted,但得靠正则解析,不稳定。
实操建议:
- 监控脚本一律走
INFORMATION_SCHEMA.INNODB_TRX+INFORMATION_SCHEMA.PROCESSLIST关联,避免解析文本出错 -
SHOW ENGINE INNODB STATUS仅用于人工排查时快速定位谁在等谁 - 注意
INFORMATION_SCHEMA表查询会加 MDL 锁,高并发下别每秒刷一次,5–10 秒间隔更安全
如何识别“隐性”行锁升级成表锁
不是所有 SELECT ... FOR UPDATE 都只锁命中行。当 WHERE 条件没走索引、或用了范围扫描但索引不覆盖、或遇到 NULL 值比较时,InnoDB 可能退化为间隙锁(Gap Lock)甚至临键锁(Next-Key Lock),最终导致看似无关的插入被堵住。
实操建议:
- 用
EXPLAIN确认语句是否走了预期索引,尤其注意type是range还是ALL,key字段是否为空 - 开启
innodb_lock_wait_timeout并设低值(如 3 秒),配合应用层日志快速暴露长等待 - 在业务低峰期执行
SELECT * FROM INFORMATION_SCHEMA.INNODB_LOCK_WAITS,它直接给出blocking_trx_id和blocked_trx_id,比肉眼扫SHOW ENGINE快得多
Prometheus + Grafana 监控锁指标该抓哪些字段
裸查 SQL 不够,得把锁行为转成时序指标。核心不是“有没有锁”,而是“锁持续多久”“谁在等”“等了几次”。关键字段来自 INFORMATION_SCHEMA.INNODB_TRX 和 INFORMATION_SCHEMA.INNODB_LOCK_WAITS。
实操建议:
- 导出
trx_wait_started时间戳,计算NOW() - trx_wait_started得到“当前等待时长”,作为mysql_innodb_trx_wait_seconds指标上报 - 统计
SELECT COUNT(*) FROM INFORMATION_SCHEMA.INNODB_LOCK_WAITS,作为mysql_innodb_lock_waits_total计数器,每分钟采集一次即可 - 避免直接暴露
trx_query到 Prometheus 标签里——SQL 太长且高基数,会撑爆内存;改用哈希(如MURMUR3)做query_hash标签
为什么 performance_schema.data_locks 开启后性能掉得厉害
默认关闭,一开就可能让 QPS 掉 10%–20%。因为每个加锁/释放锁动作都要写入该表,尤其在高频小事务场景下,锁事件远多于 SQL 执行次数。
实操建议:
- 仅在诊断期临时开启:
UPDATE performance_schema.setup_consumers SET ENABLED = 'YES' WHERE NAME = 'global_instrumentation';,完事立刻关 - 日常监控完全不用它,
INFORMATION_SCHEMA.INNODB_TRX已足够反映活跃锁状态 - 如果非要用,至少关掉
events_statements_history_long这类重型 consumer,否则磁盘 I/O 和内存增长不可控
锁监控最易被忽略的一点:不要只盯“正在等锁”的事务,更要定期检查 trx_state = 'RUNNING' 但 trx_started 超过 30 秒的“慢事务”——它们很可能已持锁不放,只是还没触发等待。











