MySQL 高频面试题-01
在去面试之前,很多人天天背“八股文”,结果一到现场被面试官稍微一变形就问懵了。比如:
“你天天说 B+ 树,那为什么不用 B 树?不用红黑树?它俩到底差在哪?”
“既然索引能加速,那我把所有字段全加上索引不就完事了?”
今天不聊那些课本上的理论,直接从面试官的抓人眼球的提问逻辑出发,复盘 4 个最核心、最容易被深挖的 MySQL 高频大坑。
一、 铁打的 B+ 树:为什么红黑树和 B 树不招人待见?
面试官最喜欢问:“为什么 MySQL 索引底层要用 B+ 树,而不是 B 树或者红黑树?”
面试官的潜台词:我不是想听你背诵 B+ 树的定义,我想看你懂不懂磁盘 I/O 的代价。
我们可以把红黑树、B 树、B+ 树的核心差异直接拉一个对比:
| 树的数据结构 | 为什么不用它? / 为什么选它? | 一句话人话解释 |
| 红黑树 (Red-Black Tree) | 高度太高。它是二叉树,数据一多,树的高度就会飙升。 | 查个数据要下好几十层,每一次下层都是一次磁盘 I/O 寻道,慢到吐血。 |
| B 树 (B-Tree) | 叶子和非叶子节点都存数据。导致一个磁盘页能存的索引变少。 | 树变胖了,但不够矮。而且做范围查询(比如 id > 10)时,得在树里来回上跳下窜。 |
| B+ 树 (B+ Tree) | 绝配。只有叶子节点存数据,非叶子节点只存索引。叶子节点之间还有双向链表。 | 树极矮(通常 3-4 层就能存千万级数据)。非叶子节点能塞更多索引,范围查询顺着链表一拉到底。 |
避坑核心
记住这个数字:InnoDB 的一个页默认是16KB。
如果是 B+ 树,非叶子节点不存指针和索引之外的 Data,那一个页能存上千个键值。
3 到 4 层的 B+ 树,就能轻松撑起千万级别的数据查询,这意味着找任何一条数据,最多只需要 3 到 4 次磁盘读写。
二、 聚簇索引 vs 非聚簇索引:到底回了两次家?
很多人分不清这两个概念,经常在“回表”这里被面试官绕进去。
聚簇索引(Clustered Index):
人话版:索引和数据是在一起的。叶子节点上存的就是这一行的完整数据。
注意:一张表只能有一个聚簇索引(一般是主键)。如果没有主键,MySQL 会自己找个唯一索引或者隐藏的 row_id。
非聚簇索引 / 二级索引(Secondary Index):
人话版:索引和数据分家了。叶子节点上存的是主键的值。
面试名场面:什么是回表?怎么避免?
看下面这两个 SQL(假设 age 字段加了普通索引):
SQL
-- SQL A SELECT id, age FROM users WHERE age = 18; -- SQL B SELECT id, name, age FROM users WHERE age = 18;SQL A 不需要回表(覆盖索引):因为通过 age 索引树找到了叶子节点,叶子节点上刚好有 age 和主键 id,面试官要的数据都在这了,直接返回!
SQL B 需要回表:拿着 age 索引树找到主键 id 之后,发现面试官还要 name。完了,age 树上没有 name,只能拿着主键 id,再去聚簇索引树里重新查一遍,拿到完整的行数据。这个过程就叫回表。
优化老鸟经验:尽量不要写 SELECT *。用联合索引把高频查询的字段包进来,达成覆盖索引,直接干掉回表,性能能飙升。
三、 事务隔离级别:MVCC 是怎么解决“幻读”的?
这个是全场最难啃的骨头,AI 写的文章喜欢堆砌一堆“读未提交、读已提交、可重复读、串行化”,毫无重点。面试官一般怎么问?
“MySQL 默认是 RR(可重复读)级别,它解决幻读了吗?怎么解决的?”
标准答案与细节拆解
答案是:部分解决了。MySQL 采用了MVCC(多版本并发控制)+ 锁(间隙锁/临键锁)的组合拳。
对于普通的 SELECT(快照读):
通过Read View(读视图)和Undo Log(回滚日志)的版本链来解决。每次读取都是读取当前事务开始时的那个“快照”,别的事务新插入的数据它根本看不见,所以不会出现幻读。
对于 SELECT ... FOR UPDATE 或者 UPDATE(当前读):
这时候不能看快照了,必须看最新数据。MySQL 就会直接祭出Gap Lock(间隙锁)或者Next-Key Lock(临键锁)。比如你锁定了 id 在 5 到 10 之间的区间,其他事务在这期间想插入一个 id = 7 的数据?对不起,直接阻塞,等我事务提交了你才能动。
四、 慢 SQL 优化:别一上来就说加索引,先看执行计划!
面试官:“你线上遇到过慢 SQL 吗?怎么排查优化的?”
避坑:千万别答“加索引”。正确的工程思维是先排查,后定位,再优化。
老鸟的规范排查三步法
1. 定位慢查询
线上开启 slow_query_log(慢查询日志),把超过比如 1s 的 SQL 全部抓出来。
2. 扔进 EXPLAIN 分析
在 SQL 前面加上 EXPLAIN,重点看这几个指标:
type(访问类型):如果出现 ALL(全表扫描)或者 index(全索引扫描),那基本上就是要挨板子了。至少要优化到 range(范围扫描)或者 ref。
key:实际用到的索引。如果是 NULL,说明没走索引。
rows:预估扫描的行数。这个数越大越危险。
Extra:
如果看到 Using filesort(用到了文件排序,没走索引排序)或者 Using temporary(用了临时表,比如复杂的 GROUP BY),必须优化!
如果看到 Using index,说明触发了覆盖索引,非常完美。
3. 针对性优化方案
索引失效了:检查是不是对字段写了函数(比如 WHERE YEAR(create_time) = 2026)、隐式类型转换(字符串没加单引号)、或者违背了最左匹配原则。
单表数据量太大:考虑冷热数据分离、或者是历史数据归档。
总结:给面试官留下好印象的口诀
面试回答 MySQL 问题,记住三个词:磁盘I/O、空间开销、数据一致性。任何底层的设计(为什么用 B+ 树、为什么要回表、为什么用 log),都是在平衡这三者的关系。
如果你觉得这篇复盘对你有帮助,点赞、收藏、关注三连走一波,祝大家都能拿到心仪的 Offer!
