意向排他锁(ix)是表级锁,行级排他锁(x)是行级锁,二者不直接冲突;ix仅用于表级锁兼容性检查并声明修改意图,不阻塞行级操作,真正阻塞x锁的是同记录上的x/s锁。

意向排他锁(IX)和行级排他锁(X)根本不在同一粒度上竞争
因为IX是表级锁,X是行级锁,InnoDB的锁兼容性判断机制压根不会让它们“碰面”去冲突。IX只参与表级锁的兼容性检查(比如有人要LOCK TABLE t WRITE,就得看表上有没有IX),而行级X锁的加锁流程在进入行记录前,已经由引擎自动完成了对表IX锁的持有——此时IX早已存在,后续X锁只是基于它继续向下加,不触发新兼容性校验。
IX锁存在的唯一目的就是“声明意图”,不是用来拦人的
它不阻塞任何行级操作,只服务于表级锁请求的快速拒绝。典型场景:
– 事务T1执行UPDATE t WHERE id = 100(命中索引),InnoDB自动加IX + 行X;
– 此时事务T2想执行LOCK TABLE t READ,发现表上有IX,立刻拒绝(因为S锁与IX不兼容);
– 但T3执行UPDATE t WHERE id = 200完全不受影响,照样能拿到自己的IX(可重入)和行X锁。
关键点:IX之间是互相兼容的,多个事务可以同时持有同一张表的IX锁。
真正阻塞行X锁的,从来都不是IX,而是其他事务持有的同一条记录上的X或S锁
行级X锁是否能成功,取决于目标记录当前是否有未释放的锁:
– 若该行已被另一事务持有了X锁,当前事务必须等待;
– 若该行被持有了S锁,也必须等待(X与S互斥);
– 但无论表上有没有IX,只要没人在动这条记录,X锁就能立刻加上。
换句话说:IX只是告诉别人“我打算改这表里的某些行”,但它本身不占着任何具体行——所以它拦不住别人改别的行,也拦不住自己再改更多行。
手动加表锁时才会暴露IX的实际作用
如果你用LOCK TABLE t WRITE,InnoDB会尝试获取表级X锁,这时会检查:表上是否存在IS或IX锁?只要有一个,就直接等待;
但如果你只是跑普通DML(如UPDATE、DELETE),InnoDB全程自动管理IX/X配合,你根本感知不到IX的存在——它就像空气,只有当你要强行关整扇门(表锁)时,才突然发现门口贴了张“内有施工”的告示(IX),而告示本身并不挡路。
容易忽略的一点:IX是隐式加的,你无法用SQL显式申请或释放它,也不该试图绕过它——所有行级写操作都强制依赖它完成表级语义校验。











