意向锁是表级元信息,不参与行锁控制,仅加速表锁与行锁兼容性判断;is/ix互不冲突但均与表级x锁冲突,且仅在表锁申请时被检查,自身不引发等待。

意向锁本身不参与行级并发控制,只服务于表锁与行锁之间的快速兼容性判断——它不是“锁资源”,而是“锁意图的声明”。
意向锁的本质是元信息,不是资源锁
IS 和 IX 锁不绑定具体数据行,也不限制其他事务读写任何行。它们只是在表级别打个标记:“我接下来要对某些行加 S/X 锁”。InnoDB 用这个标记代替全表扫描行锁状态,把 O(N) 检查降为 O(1)。所以只要不碰表锁,IS/IX 就全程隐身。
- 你执行
SELECT ... FOR UPDATE,InnoDB 自动加IX+ 行X锁:行锁负责阻塞其他事务改那几行,IX只管告诉后续想加表锁的人“别急,有人正动数据” - 另一个事务同时执行
SELECT * FROM t WHERE id = 5(走索引),它只申请行S锁,跟IX无任何兼容性检查——因为行锁和意向锁属于不同粒度层,互不干涉 - 即使表上有未提交事务留下的
IX,只要你不执行LOCK TABLES t WRITE或ALTER TABLE这类需要表级排他权限的操作,就完全感知不到它的存在
真正触发阻塞的,是表锁与意向锁的冲突规则
意向锁只在表锁申请时才被检查,且只按预设规则响应。它自己从不主动等待,也不让别人等它。
-
IS与表级X锁冲突 → 因为“有人准备读部分行”和“我要独占整张表”无法共存 -
IX与表级S或X锁都冲突 → “有人准备写部分行”意味着整表读可能看到不一致快照,整表写更不能冒险 - 但
IS和IX彼此兼容:多个读、读+写事务可以同时声明意图,互不阻塞 - 关键点:
SHOW ENGINE INNODB STATUS的LOCK WAIT段里根本不会出现IS/IX—— 它们不构成等待链,只影响表锁是否能立刻获得
全表扫描操作为什么会被卡住?
像没走索引的 UPDATE t SET a=1 或 SELECT * FROM t(配合 FOR UPDATE)这类操作,会先尝试加 IX,再逐行加锁。如果此时有其他事务正持有表级 X 锁(比如 LOCK TABLES t WRITE),那么 IX 申请就会被阻塞——但注意,阻塞源是表锁,不是意向锁本身。
- 换句话说:不是
IX在拦路,而是表X锁拒绝让任何IX进来 - 同样,如果一个事务已持
IX(比如刚执行完UPDATE但没提交),另一个会话执行LOCK TABLES t WRITE就会卡住,直到IX释放 - 这种“卡”容易被误认为是意向锁在阻塞,其实是表锁机制在严格执行多粒度锁的兼容规则
最容易忽略的一点:意向锁由 InnoDB 隐式管理,你既不能手动加,也无法绕过。它不出现在你的 SQL 里,却默默决定了表锁能否秒级获取——真正复杂的从来不是意向锁本身,而是你没意识到:那个看似无关的 SELECT FOR UPDATE,已经悄悄在表上挂了一把 IX,正等着某条 ALTER TABLE 命令撞上来。











