大厂后端面试的"必考四大件"之一(Redis / MySQL / JVM / 并发)。
本模块按 架构 → 存储引擎 → 事务并发 → 日志 → 性能优化 → 高可用 → 新特性 七层组织,每篇都按 senior 标准写:原理 + 取舍 + 面试追问 + 生产踩坑 + 答题模板。
| 文档 | 一句话定位 |
|---|---|
| MySQL 架构总览 | 接入 / Server / 引擎 / 系统文件四层 + 引擎对比 |
| SQL 语句执行过程 | 查询流程 + 更新流程 + 两阶段提交(高频题) |
| 文档 | 一句话定位 |
|---|---|
| InnoDB 存储引擎 | Buffer Pool / Change Buffer / Double Write / AHI / 后台线程 |
| 索引 | B+Tree / 聚簇索引 / 最左前缀 / 索引下推 / 失效场景 |
| explain | type / key_len / Extra 全解读 + 实战案例 |
层次关系:事务原理(基础)→ 隔离级别(行为)→ MVCC(快照机制)+ 锁(互斥机制)→ 死锁(错乱处理)。
[事务的原理] ← ACID + 三大日志映射 ↓ [事务的隔离级别] ├─ MVCC ← 快照读,解决脏读 / 不可重复读 / 部分幻读 └─ 锁机制 ← 解决当前读 / 写写 ↓ [死锁分析] ← 锁冲突的兜底排查
| 文档 | 一句话定位 |
|---|---|
| 事务的原理 | ACID 与 undo / redo / binlog 映射 |
| 事务的隔离级别 | 四级别 + RC vs RR 生产选型 + 幻读真相 |
| MVCC | 隐式字段 + 版本链 + ReadView + RC/RR 唯一区别 |
| 锁机制 | 全局 / 表 / 行 / 间隙 / 临键锁 + 加锁规则总结 |
| 死锁分析 | 5 种典型模式 + LATEST DETECTED DEADLOCK 排查 |
| 文档 | 一句话定位 |
|---|---|
| 三大日志 | redo / undo / binlog 对比 + 两阶段提交 + group commit |
| 文档 | 一句话定位 |
|---|---|
| SQL 优化与慢查询分析 | 9 类优化手法 + pt-query-digest + 服务器调优 |
| 数据库设计与范式 | 三范式 + 反范式实战 + E-R 建模 + 订单系统设计 |
| MySQL 开发规范 | 7 大类军规 + 每条背后的事故 |
| 文档 | 一句话定位 |
|---|---|
| 主从复制 | 三线程 + 异步/半同步 + GTID + 主从延迟治理 |
| 备份与恢复 | mysqldump / Xtrabackup / PITR 时间点恢复 / 备份策略与验证 |
| 分库分表 | 四象限拆分 + 分片键 + 分布式新问题 + NewSQL 替代 |
| 文档 | 一句话定位 |
|---|---|
| MySQL 8.0 新特性 | 窗口函数 / CTE / 隐藏索引 / Hash Join / 原子 DDL / JSON |
被问到这些题,直接跳到对应文档:
| 高频题 | 跳转 |
|---|---|
| MySQL 架构有几层? | 架构总览 |
| InnoDB 和 MyISAM 区别? | 架构总览 - 引擎对比 |
| 一条 update 语句的全过程? | SQL 执行过程 - 更新流程 |
| 为什么要两阶段提交? | SQL 执行过程 - 两阶段提交 |
| 崩溃恢复时事务怎么定生死? | SQL 执行过程 / 日志 |
| Buffer Pool 改良 LRU 是怎么回事? | InnoDB - 改良 LRU |
| Change Buffer 解决什么问题?为什么不对唯一索引生效? | InnoDB - Change Buffer |
| Double Write 解决什么?为什么 redo log 不够? | InnoDB - Double Write |
| MySQL 索引为什么用 B+Tree? | 索引 - 为什么是 B+Tree |
| 聚簇索引和非聚簇索引区别? | 索引 - 聚簇 vs 非聚簇 |
| 什么是回表?覆盖索引?索引下推? | 索引 - 回表与覆盖 |
| 最左前缀原则?为什么范围列后续断索引? | 索引 - 组合索引 |
| 索引为什么会失效? | 索引 - 索引失效 |
| EXPLAIN 怎么看? | explain |
| Using filesort / Using temporary 怎么办? | explain - Extra |
| ACID 各靠什么实现? | 事务的原理 |
| undo log 什么时候删? | 事务的原理 |
| 脏读 / 不可重复读 / 幻读区别? | 事务的隔离级别 |
| MySQL 默认隔离级别是什么?为什么不是 RC? | 事务的隔离级别 |
| RR 解决幻读了吗? | 事务的隔离级别 - RR 真的解决幻读吗 |
| MVCC 怎么实现的?RC 和 RR 在 MVCC 上的差别? | MVCC |
| ReadView 几个字段?可见性怎么判断? | MVCC - ReadView |
| 行锁是怎么实现的? | 锁机制 - 行级锁 |
| 什么是 MDL?为什么生产容易出事? | 锁机制 - MDL |
| 意向锁是什么?为什么需要? | 锁机制 - 意向锁 |
| Gap Lock / Next-Key Lock 在哪个级别才有? | 锁机制 - 行锁形态 |
| 加锁规则三原则? | 锁机制 - 加锁规则 |
| 发生死锁怎么排查? | 死锁分析 |
| 常见死锁模式? | 死锁分析 - 典型模式 |
| redo log 和 binlog 区别? | 日志 - redo vs binlog |
| binlog 三种格式怎么选? | 日志 - binlog |
| WAL 是什么?为什么 redo 顺序写比改数据页随机写快? | 日志 - redo log |
| 怎么发现慢 SQL? | SQL 优化 - 慢日志 |
| 深分页怎么优化? | SQL 优化 - 深分页 |
| count(*) 慢吗?怎么优化? | SQL 优化 - count |
| JOIN 怎么优化? | SQL 优化 - JOIN |
| Java 批量 INSERT 为什么很慢? | SQL 优化 - 批量插入 |
| 互联网公司的 MySQL 规范有哪些? | MySQL 规范 |
| 单表多大需要分库分表? | 分库分表 - 触发条件 |
| 分片键怎么选? | 分库分表 - 分片键 |
| 跨片 JOIN / 跨片事务怎么办? | 分库分表 - 分布式新问题 |
| 主从复制流程? | 主从复制 - 三个线程 |
| 主从延迟根因和治理? | 主从复制 - 延迟治理 |
| 异步 / 半同步 / 同步区别? | 主从复制 - 复制模式 |
| 三范式各是什么?区别? | 数据库设计与范式 - 三范式 |
| 互联网为什么不严格遵循范式? | 数据库设计与范式 - 反范式 |
| 订单表为什么冗余 user_name / 商品价格? | 数据库设计与范式 - 订单实战 |
| MySQL 怎么备份?逻辑还是物理? | 备份与恢复 - 逻辑 vs 物理 |
| mysqldump 加 --single-transaction 的原理? | 备份与恢复 - mysqldump |
| 误删表怎么救?什么是 PITR? | 备份与恢复 - PITR 流程 |
| 备份策略怎么定? | 备份与恢复 - 生产策略 |
| Xtrabackup 怎么实现热备? | 备份与恢复 - Xtrabackup |
| MySQL 8.0 哪些新特性? | MySQL 8.0 新特性 |
| 窗口函数和 GROUP BY 区别? | MySQL 8.0 - 窗口函数 |
| 递归 CTE 应用场景? | MySQL 8.0 - CTE |
| 隐藏索引 / 函数索引怎么用? | MySQL 8.0 - 索引能力 |
| Hash Join 解决什么问题? | MySQL 8.0 - Hash Join |
| 原子 DDL 是什么? | MySQL 8.0 - 原子 DDL |
| JSON 字段怎么建索引? | MySQL 8.0 - JSON |
| 8.0 升级要注意什么? | MySQL 8.0 - 升级注意 |
基础层
1. MySQL 架构总览 ← 全局视图
2. SQL 执行过程 ← 一条 SQL 的内部
3. InnoDB 存储引擎 ← 存储 / 内存 / 后台线程
索引与查询
4. 索引 ← 必学,最高频考点
5. explain ← 配合索引验证
事务与并发
6. 事务的原理 ← ACID + 三大日志
7. 事务的隔离级别 ← 4 级别 + RC/RR 选型
8. MVCC ← 快照读机制
9. 锁机制 ← 互斥机制
10. 死锁分析 ← 锁的兜底
11. 日志 ← undo / redo / binlog 整合
设计与优化
12. 数据库设计与范式 ← 三范式 + 反范式实战
13. SQL 优化与慢查询 ← 性能调优
14. MySQL 开发规范 ← 上线前必看
高可用
15. 主从复制 ← 高可用基础
16. 备份与恢复 ← PITR 时间点恢复
17. 分库分表 ← 横向扩展终极
新特性
18. MySQL 8.0 新特性 ← 窗口函数 / CTE / Hash Join
每篇看 答题模板 一节就够:
架构与执行
存储与索引
事务与并发
设计与优化
高可用
新特性
# 内存
innodb_buffer_pool_size = 物理内存 × 0.5~0.75
innodb_buffer_pool_instances = 8
innodb_log_buffer_size = 16M
# redo log
innodb_log_file_size = 1G ~ 4G
innodb_flush_log_at_trx_commit = 1 # 双 1 高可靠
# binlog
sync_binlog = 1
binlog_format = ROW
gtid_mode = ON
# 文件
innodb_file_per_table = ON
# 复制
slave_parallel_type = LOGICAL_CLOCK
slave_parallel_workers = 8
slave_preserve_commit_order = 1
rpl_semi_sync_master_enabled = 1
# IO(SSD)
innodb_io_capacity = 2000
innodb_flush_neighbors = 0
# 监控
slow_query_log = ON
long_query_time = 0.5
innodb_print_all_deadlocks = ON| 日志 | 层 | 类型 | 作用 |
|---|---|---|---|
| undo | InnoDB | 逻辑(反向操作) | 回滚 + MVCC |
| redo | InnoDB | 物理(页修改) | 崩溃恢复 |
| binlog | Server | 逻辑(行/SQL) | 主从复制 + PITR |
| 级别 | 脏读 | 不可重复 | 幻读 | 实现 |
|---|---|---|---|---|
| RU | ✓ | ✓ | ✓ | 不做特殊保护 |
| RC | ✗ | ✓ | ✓ | MVCC(每次新 ReadView) |
| RR | ✗ | ✗ | ✗* | MVCC(首次 ReadView 复用)+ Gap Lock |
| Serializable | ✗ | ✗ | ✗ | 全 SELECT 加 S 锁 |
* 快照读由 ReadView 解,当前读由 Next-Key Lock 解
| 索引 | 查询 | 命中 | 锁形态 |
|---|---|---|---|
| 唯一索引 | 等值 | 命中 | Record Lock |
| 不命中 | Gap Lock | ||
| 范围 | — | Next-Key Lock + 多锁一行 | |
| 普通索引 | 等值 | 命中 | Next-Key + 后续 Gap |
| 不命中 | Gap Lock | ||
| 范围 | — | Next-Key Lock |
system > const > eq_ref > ref > range > index > ALL
↑ ↑
警告 必须优化
1. 函数 / 表达式:YEAR(t)=2024
2. 隐式类型转换:phone=13800138000 (varchar)
3. 左模糊:LIKE '%xx'
4. 跳过最左前缀
5. 范围列后续列断索引
6. OR 一边无索引
7. 区分度低(性别)→ 优化器放弃
| 场景 | 配置 |
|---|---|
| 金融级零丢失 | flush_log_at_trx_commit=1 + sync_binlog=1(双 1) |
| 互联网高吞吐 | flush_log_at_trx_commit=2 + sync_binlog=100~1000 |
| 半同步避免主挂丢数据 | rpl_semi_sync_master_enabled=1 |
| 主从并行复制 | slave_parallel_type=LOGICAL_CLOCK + 8 workers |
| 版本 | 关键变化 |
|---|---|
| 5.5 | InnoDB 成为默认引擎 |
| 5.6 | 在线 DDL;GTID;ICP;多线程 Purge |
| 5.7 | JSON;并行复制;Buffer Pool 在线 resize;undo 表空间独立 |
| 8.0 | 数据字典转 InnoDB(无 .frm);窗口函数;CTE;隐藏索引;移除 Query Cache;Hash Join;ATOMIC DDL |
| 坑 | 文档 |
|---|---|
| 长事务卡 Purge → undo 膨胀 → 磁盘炸 | MVCC |
| ALTER + 长事务 → MDL 锁全表 | 锁机制 - MDL |
| 隐式类型转换吞 QPS(phone 字段不加引号) | 索引 - 索引失效 |
| 大事务拆爆从库(ROW binlog 百万事件) | 主从复制 - 延迟 |
| 索引太多 INSERT 慢一个量级 | 索引 - 单表索引数量 |
| Java 批量 INSERT 实际还是逐条 | SQL 优化 - 批量插入 |
| sync_binlog=0 主从不一致 | 日志 - sync_binlog |
| 深分页 LIMIT 1000000, 10 几十秒 | SQL 优化 - 深分页 |
| 分库分表用 order_id 当分片键 → 全分片广播 | 分库分表 - 分片键 |
| ibdata1 不收缩(没开 file_per_table) | InnoDB |
按出现频率列出:
- 索引:B+Tree → 聚簇 vs 非聚簇 → 回表 → 覆盖索引 → 索引下推 → 失效
- MVCC:隐式字段 → 版本链 → ReadView → RC vs RR → 与幻读
- 锁:全局 → 表 → MDL → 意向 → Record/Gap/Next-Key → 加锁规则
- 隔离级别:脏读/不可重复/幻读 → 4 级别 → RR 解决幻读 → RC vs RR 选型
- 日志:redo(物理 + WAL) → undo(回滚 + MVCC) → binlog(主从 + ROW) → 两阶段提交 → group commit
- 执行流程:连接 → Parser → Optimizer → Executor → Buffer Pool → 两阶段提交 → 主从
- 慢 SQL 优化:慢日志 → EXPLAIN → 索引 / SQL 改写 → 复测
- 死锁:必要条件 → InnoDB 检测 → LATEST DETECTED → 5 种模式 → 修复
- 主从:3 线程 → 异步/半同步 → GTID → 延迟根因 → 并行复制
- 分库分表:何时拆 → 分片键 → 跨片 JOIN/事务 → 全局 ID → 扩容
- 数据库设计:三范式 → 反范式动机 → E-R 建模 → 订单表为何冗余 user_name
- 备份恢复:mysqldump vs Xtrabackup → 全量 + 增量 → binlog → PITR 误删恢复 → 备份验证
- 8.0 新特性:窗口函数 → 递归 CTE → 隐藏索引 → Hash Join → 原子 DDL → JSON 索引
每条主线都对应至少一篇深度文档,按上方"高频题映射"快速跳转。
- Redis 面试模块 — 缓存与 MySQL 配合
- JVM — 应用层影响 DB 连接管理
- Concurrency — 并发原语与 MVCC 思想
- 分布式事务 — 分库分表的事务方案
- 分布式ID — Snowflake / Leaf
- 一致性哈希 — 分片算法