7分钟速通mysql的核心面试题
原视频地址:【程序员必看】MySQL各种锁详解:7分钟彻底搞懂MySQL的各种锁_哔哩哔哩_bilibili

首先要有大局观,比如你要锁东西是把整栋楼锁住还是只锁一个房间,或者干脆只锁一个抽屉呢,这就是锁的粒度,也就是锁的范围大小,在MYSQL中锁的粒度如下
MYSQL锁的粒度

- 全局锁:锁住整个数据库(相当于给整个大楼给封了),一个命令下来整个库谁也别想写数据,
- 作用:显而易见用于全库备份时使用,全库备份需要保证数据一动不动,这就是全局锁的作用了
- 表锁:锁住整张表(相当于锁一个房间),像老一点的MyISAM引擎默认就是表锁。
- 好处:简单直接,开销小
- 坏处:只要有一个人在房间操作其他所有人都要在门口排队,即并发差
- 行锁:锁住当行数据(相当于只锁一个抽屉),这也是目前InnoDB用的
- 好处:并发高,你给你的数据我改我的数据只要不是同一行数据咱两就互不影响
- 坏处:开销大(管一堆钥匙,要比只管大门钥匙要麻烦很多),可能死锁(你拿着我的钥匙我拿着你的钥匙两人就卡着不动了)
MYSQL锁的派别

- 悲观锁:它认为只要我改数据肯定就有人给我抢,所以它在干活前就用select…for update语句来锁住把数据锁的死死的,谁也别想动
- 场景:用在秒杀,抢库存这一类高并发的场景中(写多读少),并发写操作多,冲突概率极大必须先下手为强
- 乐观锁:它是乐天派,认为改数据时没那么多人跟我抢,所以它不加锁,直接去操作数据,只在最后要提交的时候,用版本号或者时间戳来比对一下,看看我干活的这期间有没有人都过我的数据,如果有人改了,这次提交就失败
- 场景:适合像改文章,改商品信息这一类读多写少的场景,因为它省去了加锁的开销,性能就会好很多
MYSQL中锁自带的两种基本类型

相当于在图书馆看书时
共享锁(S锁/读锁):它就等于大家一起看书,一本书可以被很多人同时看,只要大家不在上面写字就行,即读读共享,读写互斥,在mysql中可以用lock in share mode这个语句加的就是一个读锁
排他锁(X锁/写锁):当我要改书的时候必须要把这本书拿走,自己一个人改,在你改完还回来之前,别人既不能看也不能改,即写写互斥,读写互斥,在mysql中可以用for update这个语句加的就是一个读锁
MYSQL中意向锁(Intention Lock)

但它想成一个挂在表门口的通知牌,它的作用就是为了提高效率,如果事务A锁了表里面的某一行数据,这个时候事务B它想要给整个表加一个锁,那MYSQL咋办呢,难道一行一行去检查有没有行锁吗,那表里面如果有上千万行数据查到猴年马月去,这数据库直接就会被卡死,所以InnoDB就设计了这个通知牌,当事务A给某一行加锁的时候,InnoDB会自动在这个表的门口上面挂个牌子,上面写着里面有人正在操作请注意,这样当事务B想来锁整张表的时候抬头一看这张表的门口上有个牌子,立刻就知道里面有行锁,有冲突,自己得等着,效率一下就上来了,所以意向锁本身它是一个表级锁,但它不是用来锁数据的,而是用来打配合提高效率的,
有了意向锁这个帮手我们再来看看InnoDB真正在一线干活的几个核心武器
MYSQL中记录锁(Record Lock)

第一个记录锁,记录锁这就是最纯粹的行锁,指哪打哪,只锁定你查询命中的那一条记录,比如能用注解where id = 10去更新,那他就只锁ID等于10这一行,这是我们最希望看到的最理想的情况
但是如果查询条件不是唯一的呢,比如查age>18这样的范围,这时候面试必考的知识点就来了-幻读
为了解决幻读InnoDB就掏出来他的大杀器间隙锁&临键锁
MYSQL中的间隙锁&临键锁

间隙锁它不锁任何已经存在的数据,就是一个开区间,它只是锁住记录和记录之间的那个缝,比如说索引里面有10和20,那他就锁住10-20这一个区间,让你没法在这个缝隙里面插入新的数据,它就像给数据之间放了个结界,任何新的换的数据都不允许冒出来。
而临键锁呢,他就是记录锁+间隙锁,它不但锁住记录本身,还把这条记录前面的那个缝也锁住了,这才是InnoDB在可重复读隔离级别下默认使用的锁,它就像一张大网,把记录和它旁边的缝全给罩住,让幻读无处遁形
所以说为什么有了MVCC还需要锁来防止幻读呢
MVCC保证了你读的时候看不到幻影,而临键锁保证了在别人写的时候造不出幻影,一个防读,一个防写
详细的解释:
🌱 背景:MVCC 与 幻读
在 MySQL 的 可重复读(REPEATABLE READ) 隔离级别中,主要通过 MVCC(多版本并发控制) 来解决「脏读」和「不可重复读」问题。
- MVCC 的核心思想 是:每个事务在开始时,会看到一个“快照”(Snapshot)——也就是数据库在那个时间点上的一致性视图。
- 因此,当事务读取时,不管其他事务后来插入/修改了什么,它都不会看到新数据(这是 MVCC 的作用)。
但是:
MVCC 只能保证读到的内容一致,却不能防止别的事务在你读的同时插入新的记录。这就导致了“幻读”的问题。
🧩 幻读(Phantom Read)
假设事务 A 执行:
1 | SELECT * FROM users WHERE age > 20; |
此时事务 B 在事务 A 未提交期间执行:
1 | INSERT INTO users(age) VALUES(25); |
那么事务 A 再次执行相同的 SELECT 时,会发现多了一行——这就是“幻影行”,即幻读。
🔒 那为什么 MVCC 不够?
MVCC 只解决了“读一致性”的问题,它的作用是:
“你在读时,看不到别人已经提交的新数据。”
但它不能阻止别人去插入新行。换句话说:
- 你读时,看不到幻影(MVCC 起作用);
- 但别人写时,可能造出幻影(MVCC 无法阻止)。
所以当你要防止别人“造幻影”时,必须依赖 锁(尤其是 Next-Key Lock 临键锁)。
⚙️ 临键锁(Next-Key Lock)的作用
在 InnoDB 中,Next-Key Lock = 行锁 + 间隙锁。
它不只锁住已有的行,还锁住这些行之间的间隙(gap),从而阻止别的事务往这些间隙插入新行。
举例:
如果表中有
age = 18, 25, 30三行,
那么查询age > 20时,InnoDB 可能会锁住区间(20, 30),
这使得别人无法在 20~30 之间插入新数据。
🧠 理解那句话:
“MVCC 保证了你读的时候看不到幻影,而临键锁保证了在别人写的时候造不出幻影,一个防读,一个防写。”
意思是:
- MVCC:让你在读时看到的世界是稳定的,不会因为别的事务插入/修改而“看见幻影”;
- 临键锁(Next-Key Lock):防止别人在你事务期间插入“幻影行”,即从“写的角度”避免幻读的出现。
换句话说:
- MVCC 是 “读一致性” 的机制;
- 锁是 “写互斥” 的机制;
两者配合,才能在高并发下既读得快又能保证事务隔离性。
✅ 小结类比
| 机制 | 防止什么 | 方式 | 说明 |
|---|---|---|---|
| MVCC | 读到幻影(读时不一致) | 读快照 | “别人改了也不影响我现在看的” |
| 临键锁 | 别人造幻影(写时插入) | 锁定间隙 | “别人不能在我查过的范围插入新行” |
总结

总结;锁这个东西从来没有绝对的好与坏,全局锁虽然暴力,但是在备份的时候离不开它,行锁虽然精细,但你得承担死锁的风险,临键锁虽然能解决幻读,但它也可能锁住没有必要的范围,牺牲了一些性能