MySQL 8.0Notes

第 30 章:面试题精讲

zjc 于 2026-01-30 发布

这是《MySQL 8.0 源码与内核实战》的独立章节版。本章从概念、实操和生产排查三个视角展开,代码块保留了原书可直接运行的版本。 本章用面试问题串起 MySQL 8.0 内核知识,重点展示推理和证据来源。

30.1 SQL 执行路径

问题:请描述一条 SELECT 的执行流程。

回答:

dispatch_command
  -> mysql_parse
     -> resolver / rewrite
        -> optimize
           -> execute iterator
              -> handler
                 -> InnoDB row_search

追问点:索引选择、二级索引回表、执行器迭代器、MVCC 可见性。

30.2 B+Tree

问题:聚簇索引和二级索引有什么区别?

回答:

  1. 聚簇索引按主键组织完整行;
  2. 二级索引叶子存索引列和主键;
  3. 查询非覆盖列需要回表;
  4. 主键长度影响二级索引大小;
  5. 插入顺序影响页分裂。

30.3 MVCC

问题:RR 下一致性读如何工作?

回答:

  1. 记录保存 DB_TRX_IDDB_ROLL_PTR
  2. undo 形成版本链;
  3. read view 记录活跃事务;
  4. 按可见性规则沿版本链查找;
  5. RR 事务内快照保持稳定。

30.4 锁

问题:为什么 UPDATE 没走索引会锁很多行?

回答:InnoDB 行锁加在索引记录上。无合适索引时扫描范围扩大,在 RR 下还可能加 gap/next-key 锁。应先优化索引和事务范围。

30.5 Redo 与 Undo

问题:redo 和 undo 的区别是什么?

回答:redo 记录物理页修改用于崩溃恢复重做;undo 记录旧版本用于回滚和 MVCC。写入路径中先写 redo,旧版本进 undo,提交推进持久化,回滚按 undo 反向恢复。

30.6 Purge

问题:DELETE 后磁盘为什么没变小?

回答:删除先标记记录,旧版本进入 undo;purge 在最老活跃快照之后才能物理清理,并可能触发页合并。空间可复用但不一定立即归还操作系统。

30.7 DDL

问题:8.0 原子 DDL 是不是 Online DDL?

回答:不是。原子 DDL 指数据字典变更原子提交或回滚;Online 关注执行期间并发 DML,仍要区分 INSTANT、INPLACE、COPY 和 LOCK 策略。

30.8 Buffer Pool

问题:Buffer Pool 命中率低怎么办?

回答:先判断是内存不足、随机访问、大扫描、冷数据还是索引不合理。结合命中率、脏页、物理读、SQL rows examined 和工作集,再决定扩容或优化查询。

30.9 复制

问题:主从延迟如何排查?

回答:区分 IO 线程和 SQL 线程,查看 relay、applier worker、大事务、锁等待、DDL 和网络。处理大事务、并行重放、索引缺失和业务回压。

30.10 源码方法

问题:如何验证一个内核结论?

回答:固定版本,写最小复现,用 EXPLAIN 和状态定位,gdb 断点看调用栈,MTR 固化行为,最后记录版本、函数和结论。

本章小结

面试重点是把概念落到模块、路径和证据:B+Tree、MVCC、锁、日志、purge、DDL 和复制都要能从现象推到源码。

思考题

  1. 如何解释二级索引回表?
  2. read view 可见性规则有哪些?
  3. redo 和 undo 在恢复中各做什么?
  4. 原子 DDL 和 Online DDL 有什么区别?
  5. 如何证明一个锁范围结论?