意向锁
意向锁
意向锁(Intention Lock)是 InnoDB 里一个非常“战略级”的锁。它本身不锁具体数据行,而是给“表”打个标记。
在 InnoDB 中,支持行级锁。
假设事务 A 对某一行加了排他锁(X 锁)。
这时事务 B 想对整张表加表级排他锁(比如 LOCK TABLES ... WRITE)。
问题来了:
B 要不要等?
当然要等,因为 A 已经锁了其中一行。
但如果没有意向锁,B 就必须:
- 扫描整张表
- 检查每一行是否被锁
这在大表上是灾难级操作。
所以 InnoDB 引入意向锁:
- 事务 A 在给某行加 X 锁之前
- 先在表上加一个“意向排他锁”(IX)
这样,事务 B 只需要看表级锁冲突矩阵,就知道:
表上已经有 IX
我不能再加表级 X 锁
无需扫描所有行。
意向锁的两种类型
意向锁只存在于表级别,分两种:
1)意向共享锁(IS)
表示:
“我准备在某些行上加共享锁(S 锁)”
2)意向排他锁(IX)
表示:
“我准备在某些行上加排他锁(X 锁)”
注意:
IS / IX 之间不会阻塞普通行锁操作。
它们主要是用来和表级锁做冲突判断。
锁的层级结构
InnoDB 的锁是有层级的:
表级
↓
行级
当事务对某行加:
- S 锁 → 先加 IS
- X 锁 → 先加 IX
这个流程是自动完成的,开发者看不到。
锁兼容性(核心)
关键点在于它和表锁的关系:
| IS | IX | S(表锁) | X(表锁) | |
|---|---|---|---|---|
| IS | ✔ | ✔ | ✔ | ✖ |
| IX | ✔ | ✔ | ✖ | ✖ |
解释一下:
-
多个事务都可以加 IS / IX(不冲突)
-
但如果某人想加表级 X 锁
- 只要表上有 IS 或 IX
- 就会被阻塞
这就是它存在的真正意义。
一个具体例子
假设表:
1 | SELECT * FROM user WHERE id = 1 FOR UPDATE; |
发生了什么?
1)给 id=1 这一行加 X 锁
2)自动在表 user 上加 IX
此时如果另一个事务执行:
1 | LOCK TABLE user WRITE; |
会被阻塞。
因为:
IX 和 表级 X 冲突。
而且数据库只需要检查表锁冲突,不需要扫描数据行。
一个容易误解的点
意向锁不是:
- 表锁的弱版本
- 行锁的升级版
- 用来控制并发的核心锁
它只是一个“元信息标记”。
真正锁住数据的是:
- 行锁(record lock)
- 间隙锁(gap lock)
- next-key lock
意向锁只是帮它们做交通管理。
总结
意向锁 = 一个用来协调“行锁”和“表锁”的机制。
它让 InnoDB 能够:
- 同时支持高并发的行锁
- 又不牺牲表锁的语义
- 并且避免全表扫描判断冲突
它是典型的数据库工程智慧:
不是功能性锁,而是结构性优化。
一句话总结:
意向锁是 InnoDB 为了高效判断表锁和行锁冲突而设计的表级标记锁,本身不锁数据,只用于锁兼容性判断。
