MySQL 并发之王:深度拆解 MySQL 各种锁及其面试通关指南
MySQL 并发之王:深度拆解 MySQL 各种锁及其面试通关指南
蔚蓝WEILANX哈喽,大家好呀,我是蔚蓝🥰,今天我们来深入拆解一下 MySQL 的锁机制。
很多同学在面对 MySQL 锁的时候,往往感觉是一团乱麻:一会儿是表锁、一会儿是行锁;转头又冒出个间隙锁、临键锁;甚至还有听起来玄而又玄的「意向锁」。
如果你曾经被「死锁」折磨得通宵排查,或者在面试时被面试官追问“为什么 SELECT FOR UPDATE 没走索引会锁全表”,那这篇文章就是为你准备的。
不要把它当成冰冷的原理,它其实就是一套 「资源管理准则」。
粒度:到底锁了多大地方?
你可以把整张表想象成一家饭店大楼。
1. 全局锁 (Global Lock)
这是物业直接把整栋楼的大门给关了。虽然大家还能看(读),但谁也别想进来装修或入住(增删改)。这通常只用在非 InnoDB 引擎的全量备份场景。
2. 表级锁 (Table-level Lock)
假如你包下了一整个包厢或者一层楼,这就是表锁。
在 MyISAM 时代,这是常客;但在现在的 InnoDB 时代,如果你在 UPDATE 的时候没命中索引,MySQL 找不到具体的行,就会被迫“包下整张表”。这就非常恐怖了,并发性直接跌至冰点。
3. 行级锁 (Row-level Lock)
这才是真正的并发神器,也是 InnoDB 的门面方案。我们只锁具体的一个座位。 注意细节:InnoDB 的行锁,本质上是锁在「索引」上的。如果你查的那一列没索引,对不起,物理上没法定位座位,只能从头到尾全锁掉。
模式:锁的「性格」是温柔还是霸道?
1. 共享锁 (S 锁, Shared Lock)
也叫「读锁」。性格温柔:我正在看,你也可以来一起看,但咱俩谁都别改。
2. 排他锁 (X 锁, Exclusive Lock)
也叫「写锁」。性格霸道:我正在改,你们谁也别想看(指带锁读),更别想动。
模式进阶:InnoDB 的「护城河」
1. 记录锁 (Record Lock)
精准打击,锁定具体那一条记录。
2. 间隙锁 (Gap Lock)
这就是 InnoDB 防幻读的秘籍。它锁的不是真实存在的记录,而是记录之间的「真空」。就像保安站在一排座位中间,不准任何人往空的位子上插。
3. 临键锁 (Next-Key Lock)
这是 InnoDB 的默认大招:记录锁 + 间隙锁。锁定一个「左开右闭」的区间。
4. 意向锁 (Intent Lock)
这是一种表级的「打招呼」标记。当你下楼锁具体的房门时,顺便在大厅的前台做个登记(IX)。这样其他人想锁整栋楼时,看一眼登记簿就行,不用跑上跑下。
加锁机制:加锁的思想
1. 悲观锁 (Pessimistic Locking)
性格谨慎:我觉得总有人要害我。所以每次查询我都先加锁,直到改完才放。典型的就是 SELECT ... FOR UPDATE。
2. 乐观锁 (Optimistic Locking)
性格开朗:我觉得大家都是好人。我不加物理锁,只在最后更新的那一刻,拿版本号比对一下。如果别人抢先改了,我就重试或报错。
锁机制面试通关宝典
这里我把我们在面试中最常遇到的关于「锁」的深坑题整理了出来,建议反复研读。
53. 🌟 MySQL 中有哪几种锁?
MySQL 的锁可以从不同维度精准划分:
- 粒度:全局锁、表级锁、页级锁、行级锁(InnoDB 核心)。
- 兼容性:共享锁(S 锁/读锁)、排他锁(X 锁/写锁)。
- 思想模型:乐观锁、悲观锁。
- InnoDB 细分模式:记录锁、间隙锁、临键锁(Next-Key)、意向锁(IS/IX)、插入意向锁。
54. 全局锁与表锁了解吗?
全局锁 用于全库逻辑备份,阻塞所有写操作。
表锁 比较重,常见于 MyISAM 引擎或是表结构变更(DDL)。在 InnoDB 中,如果你不命中索引执行 UPDATE,锁会退化为表锁,后果不堪设想。
55. 🌟 说说 MySQL 的行锁?它的注意事项?
行锁是 InnoDB 的灵魂。
- 触发条件:加锁读
SELECT ... FOR UPDATE或数据写操作。 - 致命细节:必须显式命中索引。如果没用索引或者索引失效(比如隐式转换、模糊匹配),MySQL 会进行全表扫描加锁,直接导致行锁升级为事实上的表锁。
56. 什么是意向锁?它的意义在哪里?
意向锁(IS/IX)是表级锁。 核心意义:极大提高加表锁的判定效率。 不需要扫描整张表去确认有没有某一行被锁了,只需要看表级的一个标记即可判断冲突。
57. 记录锁、间隙锁、临键锁有什么区别?
这是决定你能不能通关 RR 隔离级别的关键:
- 记录锁 (Record Lock):锁定单条存在的索引记录。
- 间隙锁 (Gap Lock):锁定索引记录之间的真空区间,防止插入。
- 临键锁 (Next-Key Lock):左开右闭区间,是 InnoDB 默认的锁搜索单位。
58. 🌟 乐观锁和悲观锁了解吗?如何解决库存超卖?
- 悲观锁方案:
SELECT stock FROM products WHERE id=1 FOR UPDATE;在查询时直接锁定,绝对安全但并发稍慢。 - 乐观锁方案:
UPDATE products SET stock=stock-1, version=version+1 WHERE id=1 AND version=old_version;通过版本号判定,速度快但高冲突场景会有大量失败。
59. 遇到过 MySQL 死锁问题吗?如何排查?
死锁就是两个事务互相拿着对方想要的锁不撒手。
- 案例:事务 A 锁 User1 再请求 User2,事务 B 正好反过来。
- 排查命令:执行
SHOW ENGINE INNODB STATUS;。 - 解决三板斧:
- 固定加锁顺序(按 ID 大小顺序加锁)。
- 缩小事务范围(减少持有锁的时间)。
- 确保命中索引(减少锁的覆盖范围)。
碎碎念
锁这东西,学的时候觉得枯燥,一旦在生产环境遇到死锁导致整个数据库 CPU 飙升、服务大面积超时,你就会发现这种底层知识有多像「救命稻草」。
记住一句话:锁不是为了难为你,是为了在狂风暴雨的并发流中,给数据撑起一把保护伞。
好啦,今天的分享就到这里。如果你也曾经被死锁坑过,欢迎在评论区分享你的排坑经历呀!下期见,拜拜







