MySQL 社招面试题:隔离级别与锁的关系?我用一场饭局把它讲清了!

102 阅读6分钟



大家好呀,我是小米,31 岁,IT 圈摸爬滚打第 N 年,最近因为跳槽的事情,面了好几家公司。

昨天碰到一个 MySQL 社招面试题,真是既经典又阴险——

“你能讲讲 MySQL 的隔离级别和锁的关系吗?”

面试官问得云淡风轻,但我脑子里瞬间飘过四个字: “这题能套牢人”

有些同学背过四个隔离级别,但一旦让你讲“和锁的关系”,要么开始乱套,要么就干脆背一段枯燥的定义,结果面试官的眉头立刻皱成了“死锁”。

今天这篇文章,我就用一个 “饭局故事” ,帮你把隔离级别和锁的关系彻底讲透,让你下次面试直接笑着过关。

饭局开场:四种“防御级别”

想象一下,你是某大厂数据库的“宴会保安队长”,现在要守护一桌子菜,不能让人乱动。

你的饭局上有 4 种防御级别,对应的就是 MySQL 的四个隔离级别:

1、读未提交(Read Uncommitted)

就像保安睡着了,别人刚夹到菜,还没吃下去,你就能看见那筷子动作。结果别人反悔不吃了,你就看了个假动作,这就是脏读

2、读已提交(Read Committed)

保安睁一只眼闭一只眼,等人吃完、放下筷子才让别人看这道菜的情况。脏读没了,但同一道菜看两次,份量可能不一样——这就是不可重复读

3、可重复读(Repeatable Read)

保安严格了:你第一次看这桌菜啥样,就锁定那一瞬间的样子,哪怕别人偷吃,你看到的还是原样。脏读、不可重复读都没了,但有人可能会偷偷从厨房搬来新菜摆上,这就是幻读

4、串行化(Serializable)

保安直接封锁全桌,所有人排队一个一个看、一个一个吃,安全是安全了,但大家等得直跺脚,效率感人。

是不是一看就有画面感?

不过面试官可不是光听你说“隔离级别”,他们想听的重点是——这背后,MySQL 是靠什么锁来做到的?

上菜前的武器库:锁的几种类型

在这个“饭局”里,MySQL 的锁就像是不同的防御装备,主要分三类:

1、全局锁(Global Lock)

就像直接把整个宴会厅封起来,所有人禁止进出,一般只在特殊场景用,比如备份。

2、表级锁(Table Lock)

把某一桌用透明罩罩起来,别人看得到但动不了。表锁开销小,但粗暴,会让并发性能下降。

3、行级锁(Row Lock)

给某道菜贴“请勿动”标签,只保护这一道。行锁精细、并发高,但开销大,还可能发生死锁。

而 InnoDB 里用得最多的,是行锁+一些奇妙的“间隙锁”、“Next-Key Lock”组合,专门用来对付幻读。

重点来了:隔离级别和锁是怎么配合的?

接下来,我带你一边回顾隔离级别,一边看看它们到底用了哪些“锁术”来守护饭局秩序。

1. 读未提交(Read Uncommitted):几乎没锁

在这个级别,InnoDB 不会用到行锁去防读操作,因为你读取的都是别的事务未提交的数据

这种“裸奔”模式只在极特殊的场景下用,比如对实时性要求极高、能容忍脏读的场景。

加锁主要是更新的时候加排他锁(X 锁) ,其他读写几乎放行。

  • 缺点:数据安全感接近 0,饭局上就是“谁先夹谁算”。

2. 读已提交(Read Committed):提交才给看

Oracle 默认的隔离级别,InnoDB 在读数据时使用的是快照读(Snapshot Read) ,基于 MVCC(多版本并发控制),不加锁,直接读最新已提交版本的数据。

但如果是当前读(Current Read) ,比如 SELECT ... FOR UPDATE,就会给行加排他锁,防止别人同时改。

  • 好处:没有脏读;
  • 坏处:你两次查询同一行,结果可能不同(不可重复读)。

3. 可重复读(Repeatable Read):加上“幻影驱散术”

这是 InnoDB 默认的隔离级别。

它的快照读可以保证在同一个事务里,你看到的数据是一致的。

但幻读怎么办?——靠的就是间隙锁(Gap Lock)Next-Key Lock

  • 间隙锁:锁住两个索引之间的“空档”,防止有人在你没看到的地方塞新菜上桌。
  • Next-Key Lock:行锁+间隙锁的组合,既锁定已有的行,也锁住它前后的间隙。

结果就是,别人既不能改你看过的菜,也不能偷偷加新菜。

4. 串行化(Serializable):全员排队

这个级别干脆不讲武德,所有读操作都变成加锁的当前读,要么等别人事务结束,要么就乖乖排队。

MySQL 会给每次读加共享锁(S 锁) ,更新依然用排他锁。

安全拉满,性能暴跌。

MVCC:锁之外的秘密武器

很多人误以为“防并发问题只能靠锁”,其实 InnoDB 还有个“饭局监控录像”——MVCC。

MVCC 让快照读不加锁就能读到事务视图里的数据版本,这就是为什么在读已提交、可重复读下,普通的 SELECT 并不会阻塞,也不会被阻塞。

所以总结一句:

  • 快照读 → 靠 MVCC,读不加锁
  • 当前读 → 依赖各种锁(行锁、间隙锁、Next-Key Lock)

面试回答模板

如果面试官问“隔离级别与锁的关系”,你可以这样答:

MySQL 的隔离级别主要是通过 MVCC 和锁机制结合实现的:

读未提交:读取未提交版本,几乎不加锁,更新时加排他锁。

读已提交:快照读基于 MVCC,不加锁;当前读加行级排他锁,避免脏读。

可重复读:默认级别,快照读基于 MVCC;当前读除了行锁,还会加间隙锁和 Next-Key Lock,避免幻读。

串行化:所有读都变成加共享锁的当前读,更新加排他锁,完全避免并发问题。

MVCC 负责大部分读一致性,锁负责控制并发写和防止幻读。

这样回答,既讲了四个级别的特点,又点明了锁的作用,还补充了 MVCC,面试官基本会点头。

小米的饭局口诀

为了记牢,你可以背这个口诀:

未提交——几乎裸奔,

已提交——提交才真,

可重复——间隙相跟,

串行化——人人排门。

有画面、有韵律,下次面试你就不会乱。

面试只是开胃菜

说实话,隔离级别和锁的关系是 MySQL 面试里常考的硬菜,但真正的生产环境中,还得看业务场景选合适的隔离级别。

锁太多性能会掉,隔离级别太低数据会乱,这中间的平衡,才是资深开发和 DBA 的功力。

我当时在面试里用这个饭局的比喻,把面试官逗笑了,顺便把答案讲得清清楚楚,后来直接二面通知。

所以,别小看这些基础题,它们是你面试里的“定海神针”,也是数据库世界的“饭局守则”。

END

如果你觉得这个故事版的讲解有用,记得转给正在找工作的朋友。下次我再给你讲一个 “死锁与解锁” 的段子,保证你听完就会说:“原来锁也是有脾气的!”

我是小米,一个喜欢分享技术的31岁程序员。如果你喜欢我的文章,欢迎关注我的微信公众号“软件求生”,获取更多技术干货!