意向锁将表锁检测从o(n)降至o(1),通过在表级元数据中快速比对is/ix锁实现;它由innodb自动加锁、透明生效,仅优化表锁获取路径,不参与行级并发控制或死锁检测。

意向锁让表锁检测从 O(N) 降到 O(1)
没有意向锁时,InnoDB 想给整张表加 X 锁(比如执行 LOCK TABLES t WRITE),必须遍历该表所有 page、所有行,检查是否已有事务持有行级 X 或 S 锁——这在大表上可能扫描数万甚至百万行,开销巨大。有了意向锁后,只需查表级元数据中是否存在冲突的 IS 或 IX 锁,一次内存比对即可完成判断。
IS/IX 锁本身不阻塞其他意向锁,但能快速拦截冲突表锁
意向锁设计的关键在于“轻量 + 可推断”:
-
IS和IX之间完全兼容,多个事务可同时在一张表上加不同意向锁,互不影响 - 但
IS与表级X锁冲突(因为有人要读行,你却想独占整表) -
IX与表级S或X锁都冲突(因为有人已准备写行,你不能再以只读或独占方式锁全表) - 这种兼容性矩阵固化在内核中,查表动作是常数时间
意向锁由 InnoDB 自动管理,无法手动控制
你不会在 SQL 中显式看到 GET_LOCK 或 SELECT ... FOR UPDATE 触发意向锁——它完全透明:
- 执行
UPDATE t SET a=1 WHERE id=100(命中主键)时,InnoDB 先申请IX锁到表t,再对聚簇索引中对应记录加行级X锁 - 执行
SELECT * FROM t LOCK IN SHARE MODE时,先加IS锁,再对匹配行加S锁 - 即使语句没命中索引(如
WHERE name LIKE '%abc'且name无索引),InnoDB 仍会加IX锁,只是后续要为全表每一行加行锁,此时意向锁仍是唯一能快速告知“此表已被写意图占据”的标识
真正容易被忽略的点:意向锁不解决死锁,也不减少行锁数量
意向锁只优化表级锁的获取路径,它本身不参与行级并发控制。一个常见误解是“加了意向锁就安全了”,其实:
- 两个事务各自持有一行的
X锁,又互相等待对方释放,照样发生死锁——意向锁对此毫无感知 - 如果应用频繁执行无索引的
UPDATE,IX锁虽然加得快,但背后是成千上万行锁在排队等待,性能瓶颈其实在行锁争用层 -
SHOW ENGINE INNODB STATUS输出中的TRANSACTIONS部分能看到当前持有的IX/IS,但不会单独列出;它们只出现在LOCK WAIT的冲突链中,作为表级阻塞的起始节点











