is和ix是innodb自动加的表级意向锁,不可手动操作;执行lock in share mode时加is锁,for update/update/delete时加ix锁,仅用于加速表锁冲突判断,事务结束即释放。

IS 和 IX 锁不是你能手动加的锁
你执行 SELECT ... LOCK IN SHARE MODE 时,InnoDB 会自动在表上加 IS 锁;执行 SELECT ... FOR UPDATE、UPDATE、DELETE 时,会自动加 IX 锁。没有语法支持 LOCK TABLES t READ 后再手动加 IS,也没有 GET_LOCK('IS') 这种函数——IS 和 IX 是 InnoDB 内部维护的元信息,不是用户可操作对象。
常见错误现象:在监控中看到 IS 锁长时间存在,就怀疑“是不是我漏了 UNLOCK TABLES”,其实根本没这回事;或者试图用 SHOW ENGINE INNODB STATUS 中的 LOCK WAIT 区域去查谁持有 IS,结果发现全是事务 ID,没有语句上下文——因为它是隐式加的,不记录 SQL 文本。
IS/IX 的唯一作用是加速表锁冲突判断
当另一个会话执行 LOCK TABLES t WRITE(即显式 X 表锁)时,InnoDB 不需要扫描全表每一行是否被加了行锁,只需检查该表当前有没有 IS 或 IX 锁。有,就说明“这张表里至少有一行被加了 S 或 X 行锁”,于是直接拒绝表锁请求。
关键点:
-
IS和IX之间完全兼容,多个事务可以同时持有同一张表的IS和IX -
IS兼容LOCK TABLES t READ(S 表锁),但不兼容LOCK TABLES t WRITE(X 表锁) -
IX既不兼容LOCK TABLES t READ,也不兼容LOCK TABLES t WRITE - 普通 DML(如无锁
SELECT、带索引的UPDATE)完全不受IS/IX影响,它们只和行锁打交道
为什么你几乎感知不到 IS/IX 的存在
因为它们不阻塞任何常规业务 SQL:
- 两个事务分别对不同行执行
SELECT ... FOR UPDATE,各自拿到IX,互不等待 - 一个事务持
IS,另一个事务照样能对其他行做INSERT、UPDATE -
IS/IX的生命周期严格绑定事务:事务未提交前一直存在,commit/rollback 后立即释放 - 它们不会出现在
information_schema.INNODB_TRX的锁字段里,只在INNODB_LOCKS(已弃用)或performance_schema.data_locks中以TABLE类型出现
真正容易踩坑的地方是表锁和意向锁混用
如果你的应用里还残留着 LOCK TABLES 逻辑(比如某些旧版 ORM 或备份脚本),就可能触发意向锁的兼容性检查失败。例如:
- 事务 A 执行
SELECT id FROM t WHERE id = 100 FOR UPDATE→ 自动加IX - 事务 B 紧接着执行
LOCK TABLES t READ→ 被阻塞,因为IX和 S 表锁互斥 - 此时
SHOW PROCESSLIST显示事务 B 在等Waiting for table level lock,而不是行锁
这种阻塞不会报错,只会卡住,且监控工具往往只抓行锁等待,忽略表级意向锁冲突——这才是最隐蔽的问题点。











