意向锁解决的是表级锁与行级锁协调效率低的瓶颈,避免lock tables t write等操作需逐行扫描行锁状态;is由select lock in share mode触发,ix由select for update、insert、update、delete触发。

意向锁解决的不是“事务间读写同步”问题,而是表级锁与行级锁之间协调效率低这个具体瓶颈:没有它,LOCK TABLES t WRITE 这类语句就得扫描全表每一行是否被加了行锁,大表上可能卡住几秒甚至更久。
为什么表锁要查行锁状态?
当你要对整张表加排他锁(比如执行 ALTER TABLE 或 LOCK TABLES t WRITE),InnoDB 必须确保此时没有其他事务正在对这张表的任意一行做修改或独占读取——否则就会破坏一致性。没有意向锁时,系统只能去 INNODB_TRX 和锁结构里逐行比对,成本随行锁数量线性增长。
无序列表:
- 一个长事务只锁了 1 行,但表有 500 万行 → 扫描开销巨大
- 多个并发
SELECT ... FOR UPDATE可能持有数百个行 X 锁 → 检查耗时不可控 - 锁等待链变长,
SHOW ENGINE INNODB STATUS输出中 “waiting for table metadata lock” 时间飙升
IS 和 IX 锁分别对应哪些实际 SQL?
你写的 SQL 不会显式申请意向锁,InnoDB 在解析阶段就自动加上了。关键点在于:它反映的是“意图”,不是“结果”。哪怕某条 INSERT 最终没加任何行锁(例如唯一键不冲突、没触发约束检查),IX 锁照加。
无序列表:
-
SELECT ... LOCK IN SHARE MODE→ 自动加IS锁 -
SELECT ... FOR UPDATE、UPDATE、DELETE→ 自动加IX锁 -
INSERT(无论是否带唯一索引)→ 都加IX锁(为唯一性检查预留) -
REPLACE INTO或INSERT ... ON DUPLICATE KEY UPDATE→ 同样触发IX
意向锁怎么让 DDL 变得敏感?
DDL 操作(如 ALTER TABLE)通常需要获取表级 X 锁,而这个 X 锁和任何 IS 或 IX 都互斥。所以只要表上有任意一个活跃事务在跑 FOR UPDATE,哪怕只锁了一行、只执行了 10ms,DDL 就得等它提交或回滚。
容易忽略的事实:
-
SHOW ENGINE INNODB STATUS\G能看到IS/IX,但它们不会出现在information_schema.INNODB_TRX的锁统计里 - 慢查询日志里看不到意向锁等待,它藏在 metadata lock 等待中
- 用
sys.schema_table_lock_waits视图可定位谁在持IX拦着你的ALTER
真正难调试的地方在于:意向锁本身不阻塞业务 SQL,但它让表级操作变成整个事务生命周期的“全局瓶颈”。一个没注意的 FOR UPDATE 放在事务开头,后面跟了复杂逻辑,就足以拖住所有 DDL —— 而你从慢日志和锁视图里都看不到它“锁了什么”。











