MySQL 事务隔离级别面试讲解

5次阅读

四种隔离级别按严格程度从低到高依次解决:read uncommitted允许脏读;read committed解决脏读但存在不可重复读;repeatable read(mysql默认)解决脏读和不可重复读,innodb通过mvcc+间隙锁抑制幻读;serializable用读写锁彻底避免三类问题但并发最差。

MySQL 事务隔离级别面试讲解

MySQL 事务隔离级别是面试高频考点,核心在于理解四种级别如何解决脏读、不可重复读、幻读这三类并发问题,以及它们在 InnoDB 中的实现机制(主要是 MVCC + 间隙锁)。

四个隔离级别分别解决什么问题?

按严格程度从低到高排列:

  • READ UNCOMMITTED(读未提交):最低级别,允许读取其他事务未提交的数据 → 可能发生脏读
  • READ COMMITTED(读已提交):只能读到已提交的数据 → 解决脏读,但同一事务内多次读可能结果不同 → 存在不可重复读
  • REPEATABLE READ(可重复读):MySQL 默认级别。保证同一事务中多次读取结果一致 → 解决脏读和不可重复读;但对范围查询(如 SELECT … WHERE id > 10)仍可能因新插入行而看到不同结果 → 存在幻读(InnoDB 通过间隙锁+Next-Key Lock 在大部分场景下阻止了幻读)
  • SERIALIZABLE(串行化):最高级别,强制事务串行执行 → 用读写锁彻底避免脏读、不可重复读、幻读,但并发性能最差

MySQL(InnoDB)怎么实现 REPEATABLE READ?

关键不是“锁住所有数据”,而是结合两种机制:

  • MVCC(多版本并发控制):每个事务启动时会创建一个一致性视图(read view),后续查询都基于这个快照,所以不会看到其他事务之后的修改 → 实现非锁定读,解决不可重复读
  • 间隙锁(Gap Lock)和 Next-Key Lock(间隙锁+记录锁):在范围条件上加锁,防止其他事务在区间内插入新行 → 抑制幻读(例如 select * FROM t WHERE id

注意:MVCC 只用于普通 SELECT(快照读),而 SELECT … for UPDATE / LOCK IN SHARE MODE 是当前读,会触发锁机制并读最新数据。

常见面试追问点

  • RC 和 RR 下,UPDATE 的加锁行为一样吗? 不一样。RC 下只对匹配到的记录加行锁;RR 下还会加间隙锁(尤其范围条件),防止幻插入
  • 为什么 MySQL 默认用 RR 而不是 RC? 历史原因 + 主从复制安全(早期基于语句复制 SBR 时,RC 可能导致主从不一致;虽然后来默认改用 ROW 格式,但 RR 仍被保留为默认)
  • 幻读到底能不能被 RR 避免? 普通 SELECT 不会(因为 MVCC 快照),但当前读(如带 FOR UPDATE 的 SELECT)+ 间隙锁可以阻挡幻插入;不过若插入后立即 SELECT … FOR UPDATE,仍可能“看到”新行(因为锁不住未来插入),这时需要业务层或 SERIALIZABLE

怎么查看和设置隔离级别?

查看当前会话级别:

SELECT @@transaction_isolation;

设置当前会话隔离级别(重启后失效):

SET session TRANSACTION ISOLATION LEVEL READ COMMITTED;

全局设置(需 SUPER 权限,影响新连接):

SET GLOBAL TRANSACTION ISOLATION LEVEL SERIALIZABLE;

注意:修改全局级别不会影响已存在的连接,只对新建连接生效。

text=ZqhQzanResources