mysql意向锁的概念和用途
MySQL 中的意向锁(Intention Lock) 是 InnoDB 存储引擎实现的一种表级锁,主要作用是协调行级锁与表级锁之间的共存关系,提高表级锁检查的效率。它不是用来锁定具体数据的,而是表明一个事务“打算(intends to)”在表中的某些行上施加什么类型的行级锁。
理解意向锁的关键在于认识到 InnoDB 支持不同粒度的锁(表锁和行锁)共存。当一个事务想对整个表加锁(如表级 LOCK TABLES ... READ/WRITE
或某些 DDL 操作)时,它需要高效地知道表中是否已经有行被其他事务锁住了。如果没有意向锁,服务器就需要扫描每一行去检查行锁,这在大型表上是极其低效的。
意向锁解决的问题:
声明意图: 当一个事务准备在表中的某些行上施加行级共享锁(S Lock) 或行级排他锁(X Lock) 之前,它必须先在表级别上获得相应的意向锁。
意向共享锁(Intention Shared Lock, IS Lock): 表示事务打算在表中的某些行上设置共享锁(S Lock)(例如
SELECT ... LOCK IN SHARE MODE
)。意向排他锁(Intention Exclusive Lock, IX Lock): 表示事务打算在表中的某些行上设置排他锁(X Lock)(例如
SELECT ... FOR UPDATE
,UPDATE
,DELETE
,INSERT
)。高效冲突检测: 当另一个事务想要获得一个表级锁时,它只需要检查表上已有的意向锁类型,就能快速判断是否可以安全地授予表锁,而不需要逐行扫描检查行锁。
例如,如果一个事务想在表上加一个排他表锁(
LOCK TABLES ... WRITE
或某些 DDL),它需要确保表中没有任何行被其他事务锁定(无论是 S 锁还是 X 锁)。如果它看到表上存在任何IS
或IX
锁,就知道肯定有行锁存在(因为持有行锁的事务必须先获得对应的意向锁),那么表锁请求就会被阻塞,直到所有行锁(及其对应的意向锁)释放。反之,如果没有意向锁,就说明没有任何行被锁定,可以安全地授予表锁。
锁兼容性矩阵
下表显示了表级锁(包括意向锁)之间的兼容性。Y
表示兼容(可以同时持有),N
表示冲突(不能同时持有)。
X (排他表锁) | IX (意向排他锁) | S (共享表锁) | IS (意向共享锁) | |
---|---|---|---|---|
X | N | N | N | N |
IX | N | Y | N | Y |
S | N | N | Y | Y |
IS | N | Y | Y | Y |
意向锁之间兼容:
IX
和IS
之间是兼容的,IX
和IX
之间也是兼容的。这意味着多个事务可以同时声明它们打算在不同的行上设置排他锁或共享锁。这是行级并发的基础(多个事务可以同时更新不同的行)。意向锁与表锁冲突:
IX
和S
冲突:如果一个事务持有IX
(打算改某些行),另一个事务就不能获得S
(读整个表锁),因为修改可能影响读取。IS
和X
冲突:如果一个事务持有IS
(打算读某些行),另一个事务就不能获得X
(写整个表锁),因为写锁需要独占。IX
和X
冲突:显然冲突。意向锁与意向锁兼容:
IX
和IS
兼容,IS
和IS
兼容。允许读读并发和读写不同行的并发。
意向锁的作用:
提高效率: 使得表级锁的冲突检测(尤其是判断表中是否存在行锁)变得极其高效(只需检查表级的意向锁标志位),避免了昂贵的全表行锁扫描。
协调粒度: 在多粒度锁机制中(表锁和行锁共存),意向锁作为“信号灯”,清晰地表明了事务在更细粒度(行)上的操作意图,从而让表级锁的授予决策可以快速、正确地做出。
实现行级并发:
IX
锁之间的兼容性允许多个事务同时更新表中的不同行,这是 InnoDB 高并发写入的关键机制之一。
意向锁是由 InnoDB 自动管理的,开发者通常不需要(也无法)显式地请求或释放意向锁。它们在事务请求行锁时自动获取,在事务结束时释放。理解它们对于诊断锁等待、理解并发行为以及优化数据库操作至关重要。