is和ix锁由innodb自动加,不可显式申请;其作用是加速表锁冲突检测,is兼容s表锁但阻塞x表锁,ix阻塞所有表锁;生命周期绑定事务,直至commit或rollback才释放。

IS 和 IX 锁不是你手动加的,而是 InnoDB 自动加的
想在 SQL 里写 LOCK TABLE t READ 或 SELECT ... LOCK IN SHARE MODE 时顺手加个 IS 锁?不行。InnoDB 不提供任何语法让你显式申请 IS 或 IX 锁。它们是事务执行过程中由引擎内部自动加上的表级标记,开发者无法控制、不能绕过、也不能跳过。
常见误解是把 IS 当成可选优化项,或者试图用它来“提前占位”。实际它只是行锁动作发生前的一个必经步骤:只要你要对某行加 S 锁(LOCK IN SHARE MODE),InnoDB 就必须先给整张表加上 IS;只要你要对某行加 X 锁(UPDATE/DELETE/SELECT ... FOR UPDATE),就必须先加 IX。
IS/IX 的核心作用是加速表锁冲突检测
假设事务 A 正在对 t 表中 id=100 的行执行 UPDATE,此时该行已被加上 X 行锁。这时事务 B 想执行 LOCK TABLES t WRITE —— 它不需要知道具体哪一行被锁了,只需要快速确认“这张表里有没有行正被其他事务锁着”。如果没有意向锁,B 就得扫描全表所有行锁状态,代价太高。
IS 和 IX 就是这个“快速告知”机制:
-
IS表示:“我正在读某些行,别对整张表加写锁(X)” -
IX表示:“我正在改某些行,别对整张表加任何表锁(S或X)”
所以当 B 请求 LOCK TABLES t WRITE 时,InnoDB 只需检查表上是否已有 IS 或 IX,有就直接阻塞,不用查行锁细节。
IS 和 IX 之间完全兼容,但会阻塞某些表锁
多个事务可以同时持有同一张表的 IS,也可以同时持有 IX,甚至一个事务持 IS、另一个持 IX 也不冲突——因为它们只表示“打算读”或“打算写”,不互斥。
真正会被阻塞的是显式表锁操作:
-
LOCK TABLES t READ(即 S 表锁):与IX冲突,但与IS兼容 -
LOCK TABLES t WRITE(即 X 表锁):与IS和IX都冲突
换句话说:IS 不拦读表锁,但拦写表锁;IX 连读表锁都拦。
容易忽略的关键点:意向锁生命周期绑定事务
IS 和 IX 不是语句级的,而是事务级的。哪怕你只执行了一条 SELECT ... LOCK IN SHARE MODE,这个 IS 锁会一直留在表上,直到事务 COMMIT 或 ROLLBACK 才释放。
这意味着:
- 长事务会持续持有意向锁,可能意外阻塞后续的
LOCK TABLES操作 - 不会因为查询结束就释放,和行锁释放时机一致
- 在
performance_schema.data_locks中能看到它们,类型为TABLE,LOCK_MODE字段显示IS或IX
最常被忽略的是:你以为只是查了一行,没改数据,就“很轻量”,但实际上它已向整张表打了标记,并持续到事务结束。











