数据库的意向锁
1. 什么是意向锁
意向锁(Intention Lock) 是 表级锁,用来表示一个事务接下来打算在某些行上加共享锁(S锁)或排他锁(X锁)。
它本身不会直接锁住数据行,而是为了协调行锁与表锁的共存,帮助数据库快速判断表级锁是否与当前行锁冲突。
核心作用:锁兼容性检测的优化,避免在加表锁时逐行检查。
2. 为什么需要意向锁
如果没有意向锁,假设有事务在表的部分行上加了行级锁,而另一个事务想要加表级锁,数据库必须逐行扫描检查是否有锁冲突,这样开销巨大。
有了意向锁:
- 事务在加行锁前,先在表上加一个对应的意向锁。
- 当其他事务申请表锁时,只需先检查表级的意向锁,就能快速判断是否会冲突,省掉逐行检查。
3. 意向锁的类型
InnoDB 中有两种意向锁:
-
IS(Intention Shared Lock,意向共享锁)
表示事务打算在某些行上加共享锁(S锁)。 -
IX(Intention Exclusive Lock,意向排他锁)
表示事务打算在某些行上加排他锁(X锁)。
4. 意向锁的特点
-
粒度:表级
-
加锁时机:
- 事务在加行级 S 锁前,会先加 IS 锁
- 事务在加行级 X 锁前,会先加 IX 锁
-
不会阻塞行级操作,它的目的是和其他表级锁配合。
-
不会直接造成死锁,因为它只是一个标记锁。
5. 锁兼容性(MySQL InnoDB)
IS | IX | S | X | |
---|---|---|---|---|
IS | ✅ | ✅ | ✅ | ❌ |
IX | ✅ | ✅ | ❌ | ❌ |
S | ✅ | ❌ | ✅ | ❌ |
X | ❌ | ❌ | ❌ | ❌ |
- ✅ 表示两个锁可以共存
- ❌ 表示两个锁冲突
6. 举例
假设有一张 account
表,事务 T1 想修改 id=1 的记录:
BEGIN;
UPDATE account SET balance = balance + 100 WHERE id = 1;
流程:
- InnoDB 在
account
表上加 IX 锁(表示我要在某行加排他锁)。 - 在 id=1 这行加行级 X 锁。
现在事务 T2 想加表级 S 锁:
LOCK TABLE account READ;
- T2 检查表上已有 IX 锁 → 与 S 锁冲突 → 阻塞。
- 无需去逐行检查。
7. 总结口诀
行锁之前先表锁(意向锁)
IS 表示“我要加行S锁”
IX 表示“我要加行X锁”
表锁检查时先看意向锁,不用逐行查