1. 事务的 ACID 特性?分别由什么机制保证?

🎯 面试要点

  • 经典问答:"ACID 分别靠什么实现"——undo(原子)、锁+MVCC(隔离)、redo(持久)
  • 一致性是结果,其他三个是手段,面试时点一句"一致性靠约束+三者共同保证"加分

2. 四种隔离级别与三个并发问题?

三个并发问题:

四种级别(隔离性递增,性能递减):

级别 脏读 不可重复读 幻读
READ UNCOMMITTED有有有
READ COMMITTED无有有
REPEATABLE READ(MySQL 默认)无无基本无*
SERIALIZABLE无无无

*InnoDB 的 RR 级别通过 MVCC + 间隙锁/临键锁也能防止幻读(标准 SQL 说 RR 会幻读,但 InnoDB 实现更强)——这是高频考点。

🎯 面试要点

  • Oracle 默认 RC,MySQL 默认 RR(历史原因:早期 binlog 复制格式下 RR 更安全)
  • 普通 SELECT 靠 MVCC 快照读防幻读;当前读(SELECT ... FOR UPDATE)靠临键锁防幻读
  • 应用层判断:RC 还是 RR 由业务一致性要求决定,MySQL 8 可设 binlog=row 后放心用 RC(并发更高)

3. MVCC 原理?(必考,能画图讲)

MVCC(多版本并发控制):让读写不互斥。核心三件套:

可见性判断(遍历版本链找第一个可见版本):

  1. trx_id == creator → 自己改的,可见
  2. trx_id < min_trx_id → 已提交,可见
  3. trx_id >= max_trx_id → 未来事务(ReadView 之后才开的),不可见
  4. min ≤ trx_id < max → 在 m_ids 中(活跃未提交)不可见,不在则已提交可见
快照读与当前读
-- 快照读(普通 SELECT):走 MVCC,不加锁,读到 ReadView 对应的版本
SELECT * FROM user WHERE id = 1;

-- 当前读(下面这些):走最新版本 + 加锁
SELECT * FROM user WHERE id = 1 FOR UPDATE;   -- 行级写锁
SELECT * FROM user WHERE id = 1 LOCK IN SHARE MODE;  -- 共享锁
INSERT / UPDATE / DELETE

🎯 面试要点

  • RC:每次 SELECT 都生成新 ReadView → 看到最新已提交 → 不可重复读
  • RR:事务第一次 SELECT 生成 ReadView 后复用 → 快照不变 → 可重复读
  • 快照读 + 当前读混用会出"更新丢失"类问题(先快照读再 update,更新基于旧值)→ 用 FOR UPDATE 锁行

4. InnoDB 在 RR 下如何彻底防幻读?什么情况还会幻读?

🎯 面试要点

  • 临键锁锁的是"左开右闭区间"(如 (10, 20])
  • gap 锁只在 RR 及以上级别生效(RC 下只锁记录)
  • 高并发下 RR 的间隙锁容易死锁,RC + 应用层防重是常见取舍(配合乐观锁/唯一索引)

🎤 常见面试追问

  1. MVCC 的可见性判断规则?——遍历版本链:trx_id 是自己→可见;小于 min_trx_id(已提交)→可见;大于等于 max_trx_id(未来事务)→不可见;在 m_ids 活跃列表中→不可见。
  2. RC 和 RR 的 ReadView 有什么区别?——RC:每次 SELECT 都生成新 ReadView(看到最新已提交,会不可重复读);RR:第一次 SELECT 生成后复用(快照固定,可重复读)。
  3. InnoDB 的 RR 为什么能防幻读?——快照读靠 ReadView 复用(新插入的看不到);当前读(FOR UPDATE)靠临键锁(记录锁+间隙锁)锁住范围防插入。
  4. 快照读和当前读的区别?——快照读(普通 SELECT):走 MVCC 不加锁;当前读(SELECT...FOR UPDATE / UPDATE / DELETE):读最新版并加锁。
  5. MySQL 为什么默认 RR 而不是 RC?——历史原因:早期 binlog 是 STATEMENT 格式,RC 下主从复制可能不一致;现在 binlog=row 后可以放心用 RC(并发更高)。

📖 名词解释(本页术语)

术语 大白话解释
ACID事务四特性:原子性(全成或全败,undo 保证)、一致性(数据合法)、隔离性(并发互不干扰,锁+MVCC)、持久性(提交不丢,redo 保证)。
隔离级别并发事务的隔离程度四档:读未提交/读已提交/可重复读(MySQL 默认)/串行化。
脏读 / 不可重复读 / 幻读三个并发问题:读到未提交数据;同事务两次读同一行结果不同;同事务两次查询结果行数不同(有插入)。
MVCC多版本并发控制:每行存多个版本(undo 链),读操作看"符合自己快照的版本",读写不互斥——大幅提升并发。
ReadView事务做快照读时生成的"可见性视图"(记录活跃事务列表),决定能看哪个版本的数据。
undo log 版本链每次更新把旧值记录到 undo log,通过 roll_pointer 串成链——MVCC 读旧版本的依据,也是回滚的依据。
快照读 / 当前读快照读:普通 SELECT(不加锁,MVCC);当前读:FOR UPDATE/LOCK IN SHARE MODE/增删改(加锁读最新)。
间隙锁 / 临键锁间隙锁锁"记录之间的空隙"防插入;临键锁 = 记录锁 + 间隙锁(左开右闭区间),RR 下当前读用它防幻读。
⚠️ 本页面由 AI 生成,内容仅供参考,请以官方文档和实际源码为准。