Skip to content

MySQL 面试高频 100 题

定位:面试题不是学习主线,是原理掌握后的检验手段——每道题都链接回对应的原理笔记 使用方法:先理解原理→再读面试题→用面试题自测,发现自己答不出的点→回去重新理解原理


一、架构与存储引擎

1.1 一条 SELECT 语句的执行过程?

考察点:MySQL 架构分层、各组件的职责

→ 详阅 **MySQL架构总览**

答案要点

  1. 连接器:认证 + 管理连接
  2. 查询缓存(8.0 前):命中则直接返回
  3. 分析器:词法分析 → 语法分析 → 语法树
  4. 优化器:选择索引、决定 JOIN 顺序、生成执行计划
  5. 执行器:调用存储引擎 API,循环读取行
  6. 存储引擎:从磁盘/内存读取数据

1.2 为什么 MySQL 需要分层架构?

考察点:架构设计思想、可插拔存储引擎

→ 详阅 **MySQL架构总览**

答案要点:解耦查询处理和数据存储;引擎可插拔;关注点分离——Server 层专注查询优化,引擎层专注数据读写。

1.3 InnoDB 和 MyISAM 的核心区别?

考察点:事务、锁、索引、崩溃恢复

→ 详阅 **存储引擎对比**

维度InnoDBMyISAM
事务✅ ACID
锁粒度行锁表锁
聚簇索引✅ 是❌ 否
崩溃恢复✅ Redo Log❌ repair table

1.4 InnoDB 为什么这么快?

考察点:Buffer Pool、Change Buffer、预读

→ 详阅 **InnoDB架构**

答案要点:Buffer Pool 缓存热点数据减少磁盘 IO;Change Buffer 延迟合并二级索引写入;异步 IO + 预读机制。

1.5 Buffer Pool 的 LRU 为什么不是标准的?

考察点:全表扫描污染、Midpoint Insertion 策略

→ 详阅 **InnoDB架构** → 2.2 Buffer Pool

答案要点:标准 LRU 会被全表扫描污染(一次扫描把热数据挤出)。InnoDB 用 Midpoint Insertion:新页插入 5/8 位置(old 区域),1000ms 内再被访问才晋升到 young 区域。


二、索引与查询优化

2.1 为什么 MySQL 用 B+树做索引?

考察点:B+树 vs B树 vs 红黑树 vs 哈希

→ 详阅 **B+树索引结构**

答案要点

  • B+树内节点只存 key → 扇出大(~500)→ 树极矮(3-4 层存亿级数据)
  • 叶子节点链表 → 范围查询 O(N)(不需要回溯)
  • 对比:红黑树树高 log₂N(1 亿行 ≈ 27 层 IO);B 树内节点存数据扇出小且范围查询慢;哈希不支持范围

2.2 聚簇索引和二级索引有什么区别?

考察点:索引组织表、回表、覆盖索引

→ 详阅 **聚簇索引与二级索引**

答案要点

  • 聚簇索引:叶子节点存整行数据,数据和索引一体
  • 二级索引:叶子节点存主键值,需要回表查完整行
  • 覆盖索引:查询列全部在二级索引中 → 不需要回表

2.3 什么是回表?怎么避免?

→ 详阅 **聚簇索引与二级索引** → 2.3

答案要点:二级索引查到主键值→再去聚簇索引取完整行。避免方法:用覆盖索引(索引包含查询的所有列)。

2.4 最左前缀原则是什么?

考察点:联合索引的排序规则

→ 详阅 **索引优化策略**

答案要点:联合索引 (a,b,c),只有从第一列开始的连续前缀能用。因为 B+树按从左到右顺序排序。WHERE b=1 不能用到 (a,b,c) 索引。

2.5 什么是索引下推(ICP)?

→ 详阅 **索引优化策略** → 2.3

答案要点:在引擎层用索引列过滤数据,减少回表次数。Extra: Using index condition。如 WHERE name LIKE '张%' AND age=25——在二级索引层提前过滤 age=25,只有符合条件的行才回表。

2.6 EXPLAIN 的 type 列各个值什么意思?

→ 详阅 **EXPLAIN与查询优化**

从好到差:system > const > eq_ref > ref > range > index > ALL

2.7 Extra 出现 Using filesort 怎么办?

答案要点:说明排序无法走索引。解决方案——让 ORDER BY 的列加入索引。


三、SQL 与事务

3.1 MVCC 的实现原理是什么?

→ 详阅 **MVCC实现原理**

答案要点:每行有三个隐藏列(DB_TRX_ID、DB_ROLL_PTR、DB_ROW_ID);UPDATE 产生旧版本写入 Undo Log 形成版本链;事务第一次 SELECT 时创建 Read View,根据可见性规则从版本链中找到可见版本。

3.2 Read View 的可见性规则?

→ 详阅 **MVCC实现原理** → 2.3

条件可见性
DB_TRX_ID == creator_trx_id✅ 可见
DB_TRX_ID < min_trx_id✅ 可见
DB_TRX_ID >= max_trx_id❌ 不可见
DB_TRX_ID IN m_ids❌ 不可见
其他✅ 可见

3.3 RC 和 RR 在 MVCC 上的区别?

→ 详阅 **事务隔离级别**

答案要点:RC 每条语句创建新的 Read View(读到最新已提交数据),RR 整个事务复用第一个 Read View(事务内数据一致)。

3.4 不可重复读和幻读的区别?

→ 详阅 **事务隔离级别** → 2.1

对比维度不可重复读幻读
影响范围同一行(UPDATE)结果集(INSERT/DELETE)
如何解决MVCC 快照读MVCC + 间隙锁

3.5 ACID 分别由什么保证?

→ 详阅 **事务ACID实现**

答案要点:A=Undo Log(回滚)、I=MVCC+锁、D=Redo Log(WAL)、C=A+I+D+约束+应用逻辑。

3.6 为什么 WAL 快?

→ 详阅 **事务ACID实现** → 2.4

答案要点:Redo Log 是顺序追加写(~500MB/s),数据文件是随机写(~5MB/s)。顺序写比随机写快 10-100 倍。


四、锁机制

4.1 Row Lock、Gap Lock、Next-Key Lock 的区别?

→ 详阅 **行锁与间隙锁**

答案要点:Record Lock 锁单条索引记录;Gap Lock 锁间隙(防插入);Next-Key Lock = Record + Gap,锁定 (前一个值, 当前值]。

4.2 间隙锁的作用是什么?

答案要点:阻止其他事务在索引间隙中插入新行,RR 级别下防止幻读。

4.3 死锁怎么排查?

→ 详阅 **死锁分析与排查**

答案要点SHOW ENGINE INNODB STATUS 查看 LATEST DETECTED DEADLOCK 部分。关注两个事务各持有和等待什么锁。

4.4 怎么避免死锁?

答案要点:固定资源访问顺序、缩短事务、RC 代替 RR(不加间隙锁)、直接加 X 锁(避免 S→X 升级)、应用层捕获 1213 错误重试。


五、日志系统

5.1 Redo Log 和 Binlog 的区别?

→ 详阅 **Redo Log** & **Binlog**

维度Redo LogBinlog
所在层InnoDB 引擎层Server 层
类型物理日志(页+偏移+修改)逻辑/行日志
写入方式循环写(固定大小)追加写(滚动)
作用Crash Recovery(持久性)复制 + PITR

5.2 为什么需要两阶段提交?

→ 详阅 **两阶段提交与崩溃恢复**

答案要点:保证 Redo Log 和 Binlog 的一致性。否则崩溃后可能出现"Redo Log 有但 Binlog 没有"或反之,导致主从不一致。

5.3 崩溃恢复的过程?

→ 详阅 **两阶段提交与崩溃恢复** → 2.3

答案要点:扫描 Redo Log 找到所有 prepare 状态的事务 → 检查 Binlog 中是否有对应 XID → 有则补提交,无则回滚。

5.4 Binlog 三种格式的优劣?

→ 详阅 **Binlog** → 2.1

答案要点:STATEMENT 日志小但不安全(时间函数等不确定);ROW 最安全但日志大;MIXED 自动切换但不完全可控。推荐 ROW


六、高可用与架构

6.1 主从复制的三个线程分别做什么?

→ 详阅 **主从复制原理**

答案要点:Master Binlog Dump Thread(发送 Binlog);Slave IO Thread(接收写入 Relay Log);Slave SQL Thread(读取 Relay Log 重放)。

6.2 异步复制和半同步复制的区别?

答案要点:异步不等待从库(性能好、可能丢数据);半同步等待至少一个从库确认(更安全、略慢)。

6.3 复制延迟怎么解决?

答案要点:MTS 多线程复制(slave_parallel_workers)、避免大事务、从库拆分(专用复制/专用查询)。

6.4 分库分表的分片键怎么选择?

→ 详阅 **读写分离与分库分表**

答案要点:按访问频率最高的维度分片;确保 >90% 查询带分片键;数据分布均匀。


七、综合开放题

7.1 从库查询很慢,怎么排查?

考察点:系统性排查能力

答案要点

  1. SHOW PROCESSLIST 看是否有长时间运行的查询
  2. SHOW SLAVE STATUSSeconds_Behind_Master
  3. EXPLAIN 分析慢查询的执行计划
  4. 检查从库的 Buffer Pool 命中率
  5. 如果延迟严重,检查 SQL 线程是否在重放大事务

7.2 一张表 1 亿行数据,如何优化查询?

考察点:系统性的优化思路

答案要点

  1. 索引优化:检查现有索引是否合理,添加覆盖索引
  2. 分页优化:用游标分页代替 OFFSET 分页
  3. 读写分离:把查询分流到从库
  4. 数据归档:把历史数据迁移到归档表
  5. 分表:按时间或用户 ID 水平拆分
  6. 缓存:热点数据用 Redis 缓存

7.3 MySQL 死锁、主从延迟、全表扫描同时出现,先解决哪个?

答案要点

  1. 全表扫描最优先——它的影响最大(占用大量 IO 和 CPU,可能引发其他问题)
  2. 主从延迟第二——结合业务容忍度判断是否紧急
  3. 死锁第三——如果是偶发死锁,应用层重试即可;如果是高频死锁则需要排查

📚 相关链接

  • 综合解析:**综合真题解析**
  • ← 返回 **设计文档**

Knowledge4J — Java 知识库