MySQL 八股题库
这份题库重点是:你不仅能答“原理”,还要能把它落到订单、支付、订阅、退款、交易和报表分层这些项目场景里。
一、MySQL 面试里你的最佳定位
你最稳的说法是:
我对 MySQL 的理解不是只停留在 CRUD,而是长期把它用在强状态、强事务的核心业务里,比如订单、订阅、支付、退款、规则配置和交易链路。
二、高频题
1. 为什么数据库索引常用 B+ 树
标准回答
B+ 树适合数据库索引,主要因为:
- 多叉树高度低,磁盘 IO 次数少
- 非叶子节点只存索引,单页能放更多 key
- 叶子节点天然有序,适合范围查询和排序
- 比哈希更适合范围查询
项目里怎么讲
像订单、交易、订阅这类查询经常不仅是等值查,还会有范围、排序、分页,所以 B+ 树更适合。
2. 聚簇索引和二级索引有什么区别
标准回答
- 聚簇索引叶子节点直接存整行数据
- 二级索引叶子节点存的是索引列值 + 主键值
- 通过二级索引查非覆盖字段时,通常还需要回表
常见追问:为什么用自增主键
因为聚簇索引按主键组织数据,随机主键会导致页分裂更频繁,自增主键通常更稳定。
3. 什么是回表,什么是覆盖索引
标准回答
- 回表:通过二级索引找到主键后,再去聚簇索引取整行数据
- 覆盖索引:查询字段全部在索引里,不需要回表
项目里怎么讲
热点查询和高频接口里,如果能做到覆盖索引,通常能减少很多 IO。
4. 最左前缀原则是什么
标准回答
联合索引从最左列开始匹配,只有查询条件能命中最左连续前缀时,索引才能有效利用。
例子
索引 (a, b, c):
aa, ba, b, c
能比较好利用索引; 直接查 b, c 就不理想。
5. explain 主要看什么
标准回答
重点看:
typekeyrowsfilteredextra
面试更稳的说法
我不会只盯 type,更会结合 rows、是否回表、是否 filesort、是否临时表一起判断。
如果要讲得更详细,可以这样拆
1. 先看有没有走到你预期的索引
possible_keys:理论上可能用哪些索引key:实际用了哪个索引
如果 possible_keys 有值但 key 是 NULL,说明优化器最后没选索引,通常要继续看:
- where 条件是否不符合索引前缀
- 过滤条件选择性是否太差
- 有没有函数、表达式、隐式类型转换
- 扫全表是不是反而被优化器判断更便宜
2. 再看扫描方式是否健康
最常见的 type 从好到差大致可以这样理解:
systemconsteq_refrefrangeindexALL
面试里不一定非要背全顺序,但至少要知道:
const / eq_ref / ref通常比较理想range说明在走范围扫描,也不一定有问题index说明扫描了整棵索引,通常比全表扫稍好,但未必真的高效ALL基本就是全表扫描,要重点警惕
3. 再看扫描量大不大
rows:预估要扫描多少行filtered:经过 where 条件后,大概还能剩多少比例
你不能只看 type=ref 就觉得没问题。 如果 rows 非常大,哪怕走了索引,也可能只是“走了一个不太好的索引”。
4. 最后重点看 Extra
Extra 往往最能暴露问题,常见要特别关注:
Using filesortUsing temporaryUsing whereUsing indexUsing 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,一般怎么分析
我通常会按下面顺序排:
- 先确认慢在哪一层
- 真是 SQL 慢,还是连接池、锁等待、外部依赖慢
- 跑 explain
- 看是不是全表扫
- 看是不是没命中预期索引
- 看 rows 是否过大
- 看 Extra 是否有
Using filesort/Using temporary
- 回到 SQL 结构本身
- where、order by、group by 能不能和索引对齐
- 有没有
select * - 有没有大 offset 分页
- 有没有不必要的 join
- 再回到业务场景
- 这是高频接口还是低频后台查询
- 是事务型查询还是分析型查询
- 该不该继续留在 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:回滚和 MVCCredo 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 个点
- B+ 树
- 聚簇索引 / 二级索引
- 回表 / 覆盖索引
- 最左前缀
- explain
- 慢 SQL 优化
- ACID
- undo / redo / binlog
- MVCC
- 锁和隔离级别
- 大分页
- 状态机与一致性