[面试题] 什么是意向锁?
📖 版块 A:知识讲解版 (温故知新)
-
基本定义:意向锁(Intention Lock)是一种表级锁。它的核心作用是用来表达“某个事务正在,或者准备在表中的某些数据行上加锁”。在 InnoDB 引擎中,意向锁是系统自动添加的,不需要(也无法)用户手动干预。
-
主要分类:
- 意向共享锁 (IS, Intention Shared Lock):如果一个事务想要给数据行加共享锁(S 锁),它必须先获取该表的 IS 锁。
- 意向排他锁 (IX, Intention Exclusive Lock):如果一个事务想要给数据行加排他锁(X 锁),它必须先获取该表的 IX 锁。
-
核心痛点与解决方案:
- 背景:在关系型数据库中,行锁(粒度细、并发高)和表锁(粒度粗、并发低)是共存的。当一个事务想要申请一个表级锁(例如执行
ALTER TABLE结构变更,或手动LOCK TABLES)时,它必须确保这张表里没有任何一行被其他事务占用了行锁。 - 如果没有意向锁:数据库引擎需要去进行全表扫描,一行一行地去检查是否有行锁存在。面对千万级的数据表,这种 O(N) 的遍历开销是灾难性的。
- 有了意向锁:事务在给具体行加锁前,先在表级别挂一个“意向牌”(IS 或 IX)。当其他事务想加表锁时,直接看表上的“牌子”状态即可。检测效率从 O(N) 瞬间提升为 O(1)。
- 背景:在关系型数据库中,行锁(粒度细、并发高)和表锁(粒度粗、并发低)是共存的。当一个事务想要申请一个表级锁(例如执行
-
兼容性矩阵的秘密:
- 意向锁之间(IS 兼容 IS、IX 兼容 IX、IS 兼容 IX)是完全兼容的! 为什么?因为它们只是“意向”。比如我打算改第 1 行,你打算改第 2 行,我们在表级别挂的都是 IX 锁,互不影响。
- 意向锁只与表级锁(表级 S 锁、表级 X 锁)产生冲突。
🎤 版块 B:面试实战版 (高手逐字稿)
Q:什么是意向锁?它在 MySQL 中解决了什么问题?
🧠 破局思路:面试官问这道题,不仅仅是想听你背诵 IS 和 IX 的定义。这道题真正的区分度在于:你是否理解在多粒度锁机制共存(表锁与行锁共存)时,数据库是如何进行冲突检测的。如果你能把“全表扫描优化为 O(1) 标志位检测”的核心逻辑说清楚,就能直接秒杀。
💬 高手逐字稿:
简单来说,意向锁是 InnoDB 内部维护的一种表级别的锁。它存在的唯一目的,就是为了在多个粒度的锁共存时,提高冲突检测的效率。
我们可以想象这样一个极端场景:如果一个事务想要给整张表加一个排他锁(表级 X 锁),在没有意向锁的情况下,数据库怎么知道能不能加这把锁呢?它必须去逐行遍历所有的记录,确认没有任何一行被其他事务锁定了行锁。如果表里有几百万行数据,这种全表扫描的开销是完全无法接受的。
为了解决这个问题,InnoDB 引入了意向锁。规定当一个事务准备给某一行加行锁时,它必须先在表级别加一个意向锁。比如我要给第 10 行加个排他锁,我会先在表上挂个意向排他锁(IX 锁)。
这样一来,当后续有其他事务想要申请整张表的表级写锁时,它不需要去扫描全表,只需要看一眼表上的意向锁标记。如果发现表上已经挂了 IX 或者 IS 锁,说明表里肯定有某些行正被操作,它就会直接阻塞等待。通过这种方式,冲突检测的效率就从 O(N) 提升到了 O(1)。
在平时开发中有一个容易引发误解的细节,很多人觉得既然意向锁是表锁,那它会不会影响高并发?其实完全不会。
因为意向锁之间是互相兼容的。比如事务 A 给表加了 IX 锁,事务 B 同样可以持有该表的 IX 锁,因为它们可能操作的是不同的数据行。意向锁绝对不会阻塞普通的行锁操作,它只会跟试图锁定整张表的表级锁(比如普通的表读锁、写锁)发生冲突。这种设计非常巧妙,在不牺牲行锁高并发性能的前提下,完美解决了多粒度锁冲突检测的问题。