ix锁不阻塞普通读操作,因其仅为表级锁提供冲突检测的元信息;它仅阻塞整表x/s锁请求,与行级锁、mvcc快照读互不干涉。

MySQL 的 IX 锁(意向排他锁)本身不阻塞普通读操作,根本原因在于:它不是用来控制行级并发读写的,而是为「表级锁请求」提供快速冲突检测的元信息。
IX 锁到底阻塞什么?
官方手册明确定义:IX 锁仅在以下场景起阻塞作用:
- 另一个事务试图对整张表加
X(排他表锁),比如LOCK TABLES t1 WRITE—— 此时会被IX阻塞 - 另一个事务试图对整张表加
S(共享表锁),比如LOCK TABLES t1 READ—— 同样被IX阻塞 - 但对任何单行的
SELECT(快照读)、SELECT ... LOCK IN SHARE MODE(当前读加S锁)、甚至其他事务对不同行加X行锁,IX全都不拦
换句话说,IX 和 IS 之间是兼容的,IX 和 IX 之间也兼容。它的存在不是为了“拦人”,而是为了让表级锁能秒级判断“这表里有没有人在改数据”,避免逐行扫描。
为什么普通 SELECT 完全不受影响?
因为 InnoDB 的普通读默认走 MVCC 快照读,根本不申请任何行级锁,自然也不和 IX 发生兼容性判断。即使你执行的是当前读(如 SELECT ... FOR UPDATE),它申请的是行级 X 锁或间隙锁,而 IX 只是表级“占位符”,两者在不同粒度上,互不干涉。
-
IX是表级意向锁,只表明“我下面某行要加X” - 真正的阻塞来自行级
X锁本身,而不是IX - 所以两个事务分别更新不同行,各自持
IX+ 各自行X,完全并行
容易误判的典型现象
你看到 SELECT 被卡住,大概率不是 IX 搞的鬼,而是下面这些真正在挡路的东西:
- 目标行上已有其他事务的行级
X锁(比如另一条未提交的UPDATE) - 当前读触发了间隙锁或临键锁,锁住了查询条件覆盖的索引区间
- 事务持有锁时间过长(比如大事务没提交),导致后续语句排队等锁
- 误把
SHOW ENGINE INNODB STATUS里的IX当成阻塞源 —— 它只是“旁观者”,不是“肇事者”
真正需要盯紧的,永远是行级锁的持有者和等待者,而不是表级的 IX 或 IS。它们就像停车场入口的指示牌,写着“里面有人停车”,但不会拦你的车。











