锁的存储与检查
所说的锁是存在哪里的?检查时候是去哪里检查?
锁不是写在磁盘上的“文件”,而是事务在内存里申请、由 InnoDB 维护的数据结构。检查时也是查这些内存状态对外暴露的视图,而不是去翻某个表文件。
锁存在哪里?
可以分三层理解:
1. InnoDB 数据锁(先总后分)
这一类包括:行锁(record / gap / next-key)、意向锁(IS / IX)、以及 InnoDB 层的表级 S / X。下面先讲它们共同的存放与归属,再分别讲行锁和意向锁。
共性(以上锁都适用,不单指意向锁)
- 放在哪里:MySQL 进程内存里的 InnoDB 锁系统(lock system),运行时结构,不写入磁盘。
- 由谁持有:归属于某个事务(trx);事务未结束前锁通常一直存在,
COMMIT/ROLLBACK后释放。
行锁(锁什么对象)
- 加在索引记录上(B+ 树页上的记录,以及可能的间隙),不是抽象的“行对象”。
- 没走索引时,扫描范围变大,可能锁住大量记录甚至接近“锁全表”。
意向锁(表级标记,做什么用)
- 挂在表对象上的 IS / IX,表示“本事务准备或正在给某些索引记录加 S / X 行锁”。
- 不直接锁住某一行数据,只用于表锁与行锁之间的快速兼容性判断(见
intention.md里的矩阵)。
| 维度 | 行锁 | 意向锁 |
|---|---|---|
| 粒度 | 索引记录 / 间隙 | 整张表上的标记 |
| 是否挡住读写某行 | 是 | 否(本身不锁行) |
| 典型模式 | X、GAP、NEXT_KEY 等 | IS、IX |
可用下面这个最小例子理解“归属 + 对象”:
BEGIN;
SELECT * FROM user WHERE id = 1 FOR UPDATE;
-- 这时事务会持有:
-- 1) 表 user 的 IX(意向排他锁)
-- 2) PRIMARY 索引中 id=1 对应记录的 X 行锁
-- 提交前,这两类锁都属于当前事务
COMMIT; -- 提交后释放
事务 A (内存)
└── 表 user:IX
└── 索引 idx_age:行锁 / 间隙锁
└── 索引 PRIMARY:行锁
2. MDL(元数据锁,DDL 相关)
- 位置:Server 层的 MDL 哈希表(也在内存里)。
- 作用:保护表结构(
ALTER TABLE、DROP等),和 InnoDB 行锁是两套机制。 SHOW PROCESSLIST里常见Waiting for table metadata lock,查的就是这层。
3. 用户显式表锁(LOCK TABLES)
- 也是 Server + 存储引擎协作,逻辑上仍是当前会话/事务持有,同样在内存里维护,不会变成磁盘上的
.lock文件。
检查时去哪里看?
按用途选入口(你 lock.md 里已经列了,这里按“查什么”归纳):
| 想查什么 | 去哪里 |
|---|---|
| 当前有哪些 InnoDB 锁、锁在哪张表/哪个索引 | MySQL 8.0:performance_schema.data_locks |
| 谁在等谁的锁 | MySQL 8.0:performance_schema.data_lock_waits |
| 哪些事务还没提交、持锁多久 | information_schema.INNODB_TRX |
| 连接是否在等锁(粗看) | SHOW PROCESSLIST(State 如 Locked) |
| 死锁、锁等待文字详情 | SHOW ENGINE INNODB STATUS\G(TRANSACTIONS、LATEST DETECTED DEADLOCK) |
| 是否在等 MDL | SHOW PROCESSLIST + 8.0 可配合 performance_schema.metadata_locks |
MySQL 8.0 排查时优先:
-- 当前所有 InnoDB 数据锁(含 IS/IX/S/X、行锁、间隙锁等)
SELECT * FROM performance_schema.data_locks\G
-- 等待关系:blocking → waiting
SELECT * FROM performance_schema.data_lock_waits\G
-- 未提交事务(常是“谁一直占着锁”)
SELECT * FROM information_schema.INNODB_TRX\G
data_locks 里能看到例如:
LOCK_MODE:IS/IX/S/X/REC_NOT_GAP/GAP/NEXT_KEY等OBJECT_SCHEMA/OBJECT_NAME:哪张表INDEX_NAME:锁在哪个索引上
这就是把内存里的锁结构导出成可读表,不是去磁盘找“锁文件”。
MySQL 5.7 用旧视图:information_schema.INNODB_LOCKS、INNODB_LOCK_WAITS(8.0 已移除,改用 performance_schema)。
和兼容性矩阵的关系
- 矩阵:静态规则,“两种锁能不能同时存在”。
data_locks:动态快照,“此刻到底有哪些锁、在谁的事务里”。- 检查流程:新请求要加锁 → InnoDB 在内存锁表里查同对象上已有锁 → 用兼容性矩阵判断 → 冲突则进入
data_lock_waits。
一句话
锁存在 InnoDB/Server 的内存锁结构里,跟事务和索引/表对象绑定;排查时查 performance_schema.data_locks / data_lock_waits 和 INNODB_TRX,必要时用 SHOW ENGINE INNODB STATUS,而不是去数据目录或某张业务表里找。