Skip to Content
面试题库Mysql[面试题] MySQL如何实现不同隔离级别?

[面试题] MySQL如何实现不同隔离级别?

📖 版块 A:知识讲解版 (温故知新)

MySQL(以 InnoDB 引擎为例)主要通过 MVCC(多版本并发控制)锁机制 共同实现四种隔离级别:

  1. Read Uncommitted (读未提交)

    • 实现:几乎不加锁,直接读取内存中最新的记录。
    • 问题:存在脏读。
  2. Read Committed (读已提交)

    • 实现:利用 MVCC。每次执行 SELECT 语句时,都会重新创建一个新的 ReadView(一致性视图)。
    • 效果:避免了脏读,但存在不可重复读。
  3. Repeatable Read (可重复读 - 默认级别)

    • 实现:利用 MVCC。仅在事务开启后的第一次 SELECT 时创建一个 ReadView,后续查询共用同一个。
    • 解决幻读:InnoDB 在 RR 级别下通过 Next-Key Locks(记录锁+间隙锁) 来锁定范围,防止其他事务插入新数据。
    • 效果:避免了脏读、不可重复读,并在很大程度上解决了幻读。
  4. Serializable (可串行化)

    • 实现:通过 锁机制。所有的读操作都会隐式加 S 锁(共享锁),写操作加 X 锁(排他锁)
    • 效果:并发性能最低,强制事务排序执行。

MVCC 核心组件:

  • Undo Log:保存数据的历史版本链。
  • ReadView:决定当前事务能看到版本链中的哪个版本。包含四个核心字段:m_ids(活跃事务ID列表)、min_trx_idmax_trx_idcreator_trx_id

🎤 版块 B:面试实战版 (高手逐字稿)

Q:MySQL 如何实现不同隔离级别?

💬 高手逐字稿

关于 MySQL 隔离级别的实现,最核心的机制就是 MVCC(多版本并发控制)锁机制

首先,对于“读未提交(RU)”,MySQL 直接读取版本链上最新的数据,不做任何限制,所以会有脏读。而“可串行化(Serializable)”则是通过全表加锁的方式强行让事务排队,性能最差。

我们重点聊聊“读已提交(RC)”和“可重复读(RR)”,它们都是基于 MVCC 实现的,其核心区别在于 ReadView(一致性视图)生成的时机不同

RC(读已提交) 级别下,事务中每一条 SELECT 语句在执行前都会生成一个新的 ReadView。这意味着,如果另一个事务在两次查询之间提交了,由于 ReadView 是新的,当前事务就能看到最新的改动,这就导致了“不可重复读”。

而在 RR(可重复读) 级别下,事务只在执行第一条 SELECT 语句时生成一个 ReadView,整个事务过程中都复用这一个。即使其他事务提交了修改,根据 ReadView 的可见性规则(比如判断事务 ID 是否在活跃事务列表 m_ids 中),当前事务依然只能从 Undo Log 链中找回事务开始时的老版本数据,从而实现了“可重复读”。

这里有个细节容易被忽略:RR 级别是如何解决幻读的? 很多人认为 MVCC 解决了幻读,但其实 MVCC 只能解决“快照读”下的幻读。对于“当前读”(比如 SELECT ... FOR UPDATE),InnoDB 会使用 Next-Key Locks,也就是记录锁加上间隙锁(Gap Lock)。它会锁定记录之间的间隙,防止其他事务在这个范围内插入新数据,从而在底层彻底封堵了幻读的可能性。

总结来说,RC 和 RR 的本质区别就是 ReadView 的快照频率:RC 是语句级的快照,而 RR 是事务级的快照。再配合上间隙锁,RR 就成为了 InnoDB 兼顾性能与安全的默认选择。

最后更新于:
⏱️

登录后开始阅读

当前 MVP 版本只开放邮箱密码登录注册。完成登录后即可进入面试题内容。

还没有账号?先去注册