意向锁

意向锁(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 为了高效判断表锁和行锁冲突而设计的表级标记锁,本身不锁数据,只用于锁兼容性判断。