MySQL 8.0 直接移除了 INFORMATION_SCHEMA.INNODB_LOCKS 表,因其仅显示有等待关系的锁、不区分锁粒度、权限要求过高且与 Performance Schema 架构割裂;改用 performance_schema.data_locks 表,具备始终可见、字段语义清晰、支持跨表关联和细粒度权限等优势。

MySQL 8.0 直接移除了 INFORMATION_SCHEMA.INNODB_LOCKS 表,不是“弃用后推荐替代”,而是物理删除 —— 所有依赖它的脚本、监控或运维查询在升级到 8.0.3+ 后会直接报错 “Table doesn’t exist”。
为什么删掉 INNODB_LOCKS?它到底有什么问题
这个表本质是 InnoDB 内部锁结构的快照视图,但设计上存在几个硬伤:
- 只显示“有等待关系”的锁:如果一个事务持有一个 X 锁,但当前没别的事务在等它,
INNODB_LOCKS就不会返回这条记录 —— 导致你误判“没锁”,实际只是“没人卡住” - 不区分锁粒度:行锁、间隙锁、临键锁、表锁全混在一个字段里,
LOCK_MODE值含义模糊(比如INSERT_INTENTION和X,GAP容易混淆) - 权限模型不一致:查它需要全局
PROCESS权限,而很多生产环境只给 DBA 或监控账号最小权限集,这成了安全瓶颈 - 和 Performance Schema 架构割裂:它属于旧式 Information Schema 插件体系,无法与
events_waits_current、线程栈等 P_S 表做关联分析
data_locks 表解决了哪些关键问题
performance_schema.data_locks 不是简单重命名,而是重构了锁信息的采集逻辑和语义表达:
- 始终可见:只要事务持有锁(哪怕完全没人等待),
data_locks就一定有对应行 —— 真实反映“当前谁拿了什么锁” - 字段语义清晰:
LOCK_TYPE明确区分TABLE/RECORD;LOCK_MODE严格按标准命名(X,REC_NOT_GAP、S,GAP、INSERT_INTENTION) - 支持跨表关联:通过
THREAD_ID可直接连到threads表查 SQL、用户、客户端 IP;通过ENGINE_TRANSACTION_ID可连到data_lock_waits查阻塞链 - 权限更细粒度:只需对
performance_schema.data_locks有SELECT权限,无需全局PROCESS
升级后最常踩的坑:字段名和值变了,不能直接替换
很多团队把旧脚本里的 INNODB_LOCKS.LOCK_TRX_ID 直接改成 DATA_LOCKS.ENGINE_TRANSACTION_ID,结果查不到数据 —— 因为:
-
INNODB_LOCKS.LOCK_TRX_ID是十六进制字符串(如123456789ABC),而DATA_LOCKS.ENGINE_TRANSACTION_ID是十进制 bigint -
INNODB_LOCKS.LOCK_DATA在主键锁时显示主键值,但在DATA_LOCKS中,即使走主键,也可能为NULL(例如锁的是聚簇索引头页、或页面不在 buffer pool) -
INNODB_LOCKS的LOCK_INDEX字段在DATA_LOCKS中拆成了INDEX_NAME+OBJECT_NAME,且INDEX_NAME为PRIMARY时不表示“主键索引”,而表示“聚簇索引”,这点容易误解 - 旧查询习惯用
LOCK_TRX_ID关联INNODB_TRX,现在得用ENGINE_TRANSACTION_ID关联performance_schema.events_transactions_current(注意不是INNODB_TRX!该表也已弱化)
一个能跑通的最小排查链路
想快速定位“谁在等谁”,别再拼 INNODB_LOCK_WAITS,用这套组合:
SELECT r.trx_id waiting_trx_id, r.trx_mysql_thread_id waiting_thread, r.trx_query waiting_query, b.trx_id blocking_trx_id, b.trx_mysql_thread_id blocking_thread, 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;
注意:data_lock_waits 是唯一保留“请求-阻塞”映射关系的表,但它依赖 INNODB_TRX 查 SQL —— 所以仍需保留对 INNODB_TRX 的访问(它没被删,只是功能收窄)。真正彻底脱离旧 I_S 的方案,得用 events_statements_current 关联线程 ID,但那要处理更复杂的事件生命周期。
真实线上锁问题往往卡在“锁住了但没等待”,这时候只查 data_lock_waits 是空的,必须先看 data_locks 找出活跃锁,再结合事务状态和 SQL 文本判断是否异常 —— 这个思维切换,比语法迁移更重要。


















