Skip to content

MySQL 面试题集:从六个问题把知识点收口 ​

属于 S1 MySQL 深入 · 收口篇 上一篇:主从复制与高可用

前面基础篇四章 + 深入篇五章,把 MySQL 的库表/SQL、存储与 B+ 树、事务与隔离级别、索引、慢查询优化、高可用串成了一条线。这一篇换个角度——站在面试现场,把最常被问的六个问题过一遍,每题都练到"被连续追问三层还不卡壳"。

Q1:为什么索引用 B+ 树? ​

这个问题考的是你"排除法"的推导过程,而不是背结论。

你可以这样讲:索引是为了用最少的磁盘 IO 找到数据。哈希表虽然 O(1),但不支持范围查询和排序,出局;红黑树支持范围,但树太高,一次查询要几十次 IO,也出局;所以需要多叉、矮胖的树。B+ 树相比 B 树,非叶子节点不存数据、更瘦,树更矮,叶子还串成链表方便范围扫描。

追问①:3 层 B+ 树能存多少数据? 一页 16KB,非叶子每 key+指针 14B,一页约 1170 个;叶子一页约 16 行;三层 1170×1170×16≈2200 万 行。

追问②:为什么推荐自增主键? 顺序插入避免页分裂,随机主键(UUID)会频繁分裂、降低页利用率。

Q2:redo log 和 binlog 的区别?为什么两阶段提交? ​

先讲区别:redo 是 InnoDB 引擎层的物理日志,记"改了哪个数据页",用于崩溃恢复;binlog 是 Server 层的逻辑日志,记 SQL 语句,用于主从复制和数据恢复。

再讲为什么两阶段提交:两份日志是独立的,如果只写一份就崩溃,会导致主从数据不一致。两阶段提交(redo prepare → 写 binlog → redo commit)保证两份日志要么都成功、要么都失败。

追问:崩溃在 prepare 和 commit 之间怎么恢复? 看 binlog 有没有写:写了就提交(保证主从一致),没写就回滚。

Q3:MVCC 怎么实现?RC 和 RR 的区别? ​

核心三件套:隐藏列(trx_id/roll_ptr)+ undo 版本链 + Read View。每次修改写新版本、指针串成链,读的时候拿 Read View 去链上找"已提交的版本"。

追问:RC 和 RR 差在哪? Read View 的生成时机——RC 每次查询新建,RR 首次建后复用。所以 RC 不可重复读,RR 可重复读。

Q4:什么是幻读?RR 怎么解决? ​

幻读是范围查询结果的行数变了(别人 INSERT 了),注意它和"不可重复读"(行内容变了,UPDATE)的区别。

RR 解决幻读是两条腿:快照读(普通 SELECT)靠 MVCC,天然看不到新插入的行;当前读(UPDATE/FOR UPDATE)靠 next-key lock,锁住间隙挡住 INSERT。

Q5:一条 SQL 很慢,怎么排查? ​

讲出"从现象到根因"的路径:慢查询日志定位语句 → EXPLAIN 看执行计划 → 看 type 是不是 ALL、key 是不是空、Extra 有没有 Using filesort → 对症下药(加索引、改写 SQL、覆盖索引)。

追问:type=ALL 一定慢吗? 小表未必,但大表 ALL 必须优化。追问:深分页 LIMIT 100000,10 怎么优化? 延迟关联,先查主键再回表。

Q6:主从延迟的原因和解决? ​

根因是从库单线程回放追不上主库的多线程并发写,叠加"大事务、无主键"更严重。

解决:并行复制、拆小事务、加主键。追问:半同步能解决延迟吗? 不能,半同步解决的是"丢数据"(可靠性),不是延迟。


自测清单 ​

把上面六题盖住答案,能完整讲出推理过程 + 每题的追问都答上来,S1 MySQL 就达到"连续追问不卡壳"的标准了。过关后进入 S2 Redis。

持续学习,持续构建。