mysql 8.0 并未改用内存分配器存储锁信息,锁仍由 innodb 自管理;performance_schema.data_locks 仅快照上报的锁状态,非参与分配。

MySQL 8.0 并没有“改用内存分配器存储锁信息”——这是一个常见误解。锁信息本身仍由 InnoDB 自己管理,performance_schema.data_locks 表只是**读取并快照**这些内存结构,并不参与锁的分配或生命周期控制。
为什么锁信息不再存在 INNODB_LOCKS 表里?
5.7 的 INNODB_LOCKS 和 INNODB_LOCK_WAITS 是只读视图,背后依赖内部锁系统临时构造结果,存在严重缺陷:
- 查询时会触发锁结构遍历,高并发下易引发 mutex 争用,拖慢整个锁系统
- 锁对象一旦被释放(比如事务提交),视图就查不到,无法回溯分析历史锁行为
- 无法区分 GRANTED 和 WAITING 状态,只能靠关联
INNODB_LOCK_WAITS推断,逻辑脆弱
8.0 改用 performance_schema.data_locks,本质是把锁元数据统一接入 P_S 的 instrumentation 框架:InnoDB 在每次加锁/释放锁时主动上报事件,P_S 用自己的一套内存 allocator(如 PSI_memory)缓存这些快照。这不是“锁改用 P_S 分配”,而是“锁状态被 P_S 记录”。
data_locks 表里的 LOCK_DATA 为什么有时为空?
LOCK_DATA 字段取决于锁类型和索引结构,不是所有锁都能反解出具体值:
- 主键上的 RECORD 锁:能显示主键值,如
123 - 二级索引上的 RECORD 锁:显示索引列值 + 对应主键值,如
name='alice', id=456 - GAP 锁或 NEXT-KEY 锁:只显示区间端点,如
supremum pseudo-record或7, 12,但若范围过大或涉及 NULL,可能直接为NULL - 表级锁(
LOCK_TYPE = 'TABLE'):LOCK_DATA恒为空
别把它当调试工具硬凑值——它只是快照,不是实时映射。
为什么 data_locks 查询变慢或返回空?
这不是锁系统问题,而是 P_S 配置或访问方式不对:
-
performance_schema未启用对应 instrument:检查setup_instruments中wait/innodb/innodb_lock_wait是否为YES - 锁刚释放就被清理:P_S 默认只保留最近 N 条事件,
data_locks是瞬态快照,不是归档表 - 权限不足:用户需有
SELECTonperformance_schema.data_locks,且不能只靠PROCESS权限 - 没及时刷新:P_S 表不自动刷新,执行
FLUSH STATUS或等几秒再查更可靠
真正容易被忽略的是:data_locks 只反映“此刻已注册的锁”,它不包含正在排队、尚未进入 wait-for graph 的等待请求;死锁检测失败或超时前的阻塞,也未必立刻出现在这张表里。排查锁等待,必须结合 INFORMATION_SCHEMA.INNODB_TRX、SHOW ENGINE INNODB STATUS 和错误日志三者交叉验证。











