MySQL 八股题库

这份题库重点是:你不仅能答“原理”,还要能把它落到订单、支付、订阅、退款、交易和报表分层这些项目场景里。


一、MySQL 面试里你的最佳定位

你最稳的说法是:

我对 MySQL 的理解不是只停留在 CRUD,而是长期把它用在强状态、强事务的核心业务里,比如订单、订阅、支付、退款、规则配置和交易链路。


二、高频题

1. 为什么数据库索引常用 B+ 树

标准回答

B+ 树适合数据库索引,主要因为:

  • 多叉树高度低,磁盘 IO 次数少
  • 非叶子节点只存索引,单页能放更多 key
  • 叶子节点天然有序,适合范围查询和排序
  • 比哈希更适合范围查询

项目里怎么讲

像订单、交易、订阅这类查询经常不仅是等值查,还会有范围、排序、分页,所以 B+ 树更适合。


2. 聚簇索引和二级索引有什么区别

标准回答

  • 聚簇索引叶子节点直接存整行数据
  • 二级索引叶子节点存的是索引列值 + 主键值
  • 通过二级索引查非覆盖字段时,通常还需要回表

常见追问:为什么用自增主键

因为聚簇索引按主键组织数据,随机主键会导致页分裂更频繁,自增主键通常更稳定。


3. 什么是回表,什么是覆盖索引

标准回答

  • 回表:通过二级索引找到主键后,再去聚簇索引取整行数据
  • 覆盖索引:查询字段全部在索引里,不需要回表

项目里怎么讲

热点查询和高频接口里,如果能做到覆盖索引,通常能减少很多 IO。


4. 最左前缀原则是什么

标准回答

联合索引从最左列开始匹配,只有查询条件能命中最左连续前缀时,索引才能有效利用。

例子

索引 (a, b, c)

  • a
  • a, b
  • a, b, c

能比较好利用索引; 直接查 b, c 就不理想。


5. explain 主要看什么

标准回答

重点看:

  • type
  • key
  • rows
  • filtered
  • extra

面试更稳的说法

我不会只盯 type,更会结合 rows、是否回表、是否 filesort、是否临时表一起判断。

如果要讲得更详细,可以这样拆

1. 先看有没有走到你预期的索引

  • possible_keys:理论上可能用哪些索引
  • key:实际用了哪个索引

如果 possible_keys 有值但 keyNULL,说明优化器最后没选索引,通常要继续看:

  • where 条件是否不符合索引前缀
  • 过滤条件选择性是否太差
  • 有没有函数、表达式、隐式类型转换
  • 扫全表是不是反而被优化器判断更便宜

2. 再看扫描方式是否健康

最常见的 type 从好到差大致可以这样理解:

  • system
  • const
  • eq_ref
  • ref
  • range
  • index
  • ALL

面试里不一定非要背全顺序,但至少要知道:

  • const / eq_ref / ref 通常比较理想
  • range 说明在走范围扫描,也不一定有问题
  • index 说明扫描了整棵索引,通常比全表扫稍好,但未必真的高效
  • ALL 基本就是全表扫描,要重点警惕

3. 再看扫描量大不大

  • rows:预估要扫描多少行
  • filtered:经过 where 条件后,大概还能剩多少比例

你不能只看 type=ref 就觉得没问题。 如果 rows 非常大,哪怕走了索引,也可能只是“走了一个不太好的索引”。

4. 最后重点看 Extra

Extra 往往最能暴露问题,常见要特别关注:

  • Using filesort
  • Using temporary
  • Using where
  • Using index
  • Using index condition

其中面试里最值得重点讲的是:

  • Using filesort:说明排序没被索引承接,通常要看 order by 和索引是否一致
  • Using temporary:常见于 group by / distinct / 复杂排序,说明中间结果可能进临时表
  • Using index:通常意味着覆盖索引,不需要回表

一个更像做过项目的回答

我看 explain 时一般会按这个顺序:先看 key 有没有命中预期索引,再看 type 是 ref、range 还是 ALL,然后看 rows 大不大,最后重点看 Extra 有没有 filesort、temporary、回表迹象。因为很多 SQL 不是没走索引,而是走了一个不够好的索引。


6. 慢 SQL 一般怎么优化

标准回答

常见思路:

  • 补合适索引
  • 避免 select *
  • 减少回表
  • 拆复杂查询
  • 降低大 offset 分页成本
  • 把分析类查询拆去专门的分析存储

项目里怎么讲

我做慢 SQL 优化时,不会只看 SQL 本身,也会看是不是业务分层出了问题,比如本来该去 ClickHouse 的查询,硬压在 MySQL 上就一定不合适。

如果结合 explain,一般怎么分析

我通常会按下面顺序排:

  1. 先确认慢在哪一层
  • 真是 SQL 慢,还是连接池、锁等待、外部依赖慢
  1. 跑 explain
  • 看是不是全表扫
  • 看是不是没命中预期索引
  • 看 rows 是否过大
  • 看 Extra 是否有 Using filesort / Using temporary
  1. 回到 SQL 结构本身
  • where、order by、group by 能不能和索引对齐
  • 有没有 select *
  • 有没有大 offset 分页
  • 有没有不必要的 join
  1. 再回到业务场景
  • 这是高频接口还是低频后台查询
  • 是事务型查询还是分析型查询
  • 该不该继续留在 MySQL

常见问题和对应解法

场景 1:type = ALL

常见原因:

  • 没有合适索引
  • 联合索引不符合最左前缀
  • 条件列被函数包住
  • 字段类型不匹配导致索引失效

常见解法:

  • 补索引或重建联合索引
  • 改 where 条件写法
  • 避免隐式转换
  • 把函数计算下沉到写入侧或额外字段

场景 2:走了索引,但 rows 还是很大

常见原因:

  • 命中的索引选择性差
  • where 条件顺序和联合索引设计不匹配
  • 先过滤再排序的代价仍然很高

常见解法:

  • 重做联合索引,让高选择性字段尽量靠前
  • 让排序字段和过滤字段一起进索引
  • 拆查询,先缩小结果集再查详情

场景 3:Using filesort

常见原因:

  • order by 没有被索引承接
  • 排序方向和索引顺序不匹配
  • where 和 order by 组合没设计好联合索引

常见解法:

  • 让 where + order by 尽量共用同一联合索引
  • 降低排序前参与的数据量
  • 后台查询考虑异步导出或预计算

场景 4:Using temporary

常见原因:

  • group by / distinct / 多表 join 后聚合
  • 结果集过大

常见解法:

  • 改写聚合逻辑
  • 提前过滤
  • 报表类查询拆去 ClickHouse / 数仓

面试里一句更稳的总结

explain 不是看一个字段就下结论,而是执行计划和业务场景一起看。很多慢 SQL 的根因,不只是少一个索引,而是索引设计、SQL 写法和业务分层三件事同时出了问题。


7. 事务四大特性 ACID 是什么

标准回答

  • A:Atomicity 原子性
  • C:Consistency 一致性
  • I:Isolation 隔离性
  • D:Durability 持久性

更稳的说法

一致性不是单靠某一个组件保证,而是原子性、隔离性、持久性,再加约束和业务设计共同保证。


8. undo log、redo log、binlog 分别做什么

标准回答

  • undo log:回滚和 MVCC
  • redo log:崩溃恢复,保证持久性
  • binlog:Server 层逻辑日志,主从复制和数据恢复

常见追问:为什么 redo 和 binlog 要两阶段提交

为了避免存储引擎层和 Server 层日志不一致,保证崩溃恢复和主从复制的一致性。


9. MVCC 是什么

标准回答

MVCC 是多版本并发控制,主要用于快照读。它通过记录版本信息、生成 read view,并结合 undo log 读取历史版本,从而让读操作在不加锁的情况下看到一致性快照。

项目里怎么讲

我更关注它解决了什么问题:减少读写冲突,提高并发读性能。


10. 隔离级别有哪些

标准回答

  • Read Uncommitted
  • Read Committed
  • Repeatable Read
  • Serializable

InnoDB 默认是 Repeatable Read

追问:幻读怎么解决

当前读场景下,InnoDB 通过 Next-Key Lock 解决幻读;快照读主要依赖 MVCC。


11. 行锁、间隙锁、Next-Key Lock 分别是什么

标准回答

  • 行锁:锁住某条记录
  • 间隙锁:锁住某个范围间隙,不锁具体记录
  • Next-Key Lock:记录锁 + 间隙锁

面试更稳的说法

Next-Key Lock 本质上是为了解决 RR 隔离级别下的幻读问题。


12. 为什么大分页慢,怎么优化

标准回答

limit offset, size 在 offset 很大时,数据库需要先扫描大量记录再丢弃,成本很高。

常见优化

  • 记住上次最大 id 做游标分页
  • 覆盖索引 + 子查询
  • 分页场景缓存

13. 订单超时关闭为什么不适合全表扫

标准回答

量小可以扫,但量大时不适合长期扫主订单表。更好的做法是延迟队列、时间事件、Redis ZSet 或分桶任务表,到期再触发关闭。

项目里怎么讲

这个问题非常适合你拿来讲状态机、幂等和并发一致性。


14. 如何保证支付和超时关闭不打架

标准回答

核心不是加大锁,而是用状态机 + 条件更新:

  • 关闭只能 pending -> closed
  • 支付只能 pending -> paid

谁先更新成功谁生效,另一边更新不到就结束。

项目里怎么讲

支付、退款、订单关闭这类业务我会优先考虑状态机和 CAS 更新,而不是上来就靠大事务和大锁。


15. 为什么报表不放 MySQL,而放 ClickHouse

标准回答

因为报表、ROI、优化助手这类场景本质是分析型查询,不是事务型查询。MySQL 更适合业务主数据和状态数据,ClickHouse 更适合大数据量聚合分析。

这题你一定要会和项目结合

这就是你推广 ROI 项目的关键技术判断。


三、你最该主动讲的 MySQL 项目化理解

1. MySQL 放什么

  • 订单
  • 订阅
  • 支付
  • 退款
  • 规则配置
  • 广告账户 / 计划 / 后台配置

2. MySQL 不适合长期放什么

  • 原始曝光点击事件
  • 高吞吐日志类数据
  • 大数据量报表聚合分析

3. MySQL 的核心价值

不是“万能存储”,而是:

  • 事务
  • 状态
  • 一致性
  • 可追溯

四、常见追问

追问 1:为什么不是所有东西都丢到 MySQL

可以答:

因为不同数据类型对存储的诉求不一样。业务主数据和状态数据适合 MySQL,但原始事件、搜索和分析型数据应该分层。

追问 2:事务是不是越大越安全

可以答:

不是。事务边界过大反而会增加锁冲突和性能问题。复杂系统里更重要的是事务边界清晰,再配合幂等、状态机和异步补偿。

追问 3:你怎么理解一致性

可以答:

数据库事务保证的是单库内的一致性,真正业务一致性还要靠状态机、幂等、消息一致性和补偿机制。


五、你复习 MySQL 最该背的 12 个点

  1. B+ 树
  2. 聚簇索引 / 二级索引
  3. 回表 / 覆盖索引
  4. 最左前缀
  5. explain
  6. 慢 SQL 优化
  7. ACID
  8. undo / redo / binlog
  9. MVCC
  10. 锁和隔离级别
  11. 大分页
  12. 状态机与一致性