MySQL 面试题速查
本文是浓缩版速答。每题尽量一句话讲清结论;详细原理点对应链接。
一、索引
Q: 为什么 MySQL 用 B+ 树而不是 B 树/红黑树/Hash?
B+ 树非叶节点不存数据 → 一个节点能装更多 key → 树更矮 → 磁盘 IO 少;叶子节点链表 → 范围查询快。Hash 不支持范围、不支持排序。
Q: 聚簇索引 vs 二级索引?
- 聚簇索引:叶子节点存整行数据,InnoDB 主键即聚簇索引
- 二级索引:叶子节点存主键值,需要”回表”
Q: 什么是覆盖索引? → 详细
SELECT 的字段全在二级索引里,不用回表。EXPLAIN 显示 Using index。
Q: 最左前缀原则?
联合索引 (a, b, c) 只能命中 a / a+b / a+b+c,不能 b 或 b+c。
Q: 索引为什么会失效? → 12 种原因
函数运算、隐式转换、%xxx、OR 含非索引列、违反最左前缀、负向查询…
Q: 什么时候不该建索引? → 优缺点
小表、低选择性字段、写多读少、字段经常更新。
二、事务与隔离级别
Q: ACID 是什么?
- A 原子性:要么全做,要么全不做(undo log)
- C 一致性:业务规则不被破坏(前 3 项的结果)
- I 隔离性:并发事务相互不感知(锁 + MVCC)
- D 持久性:提交后不丢(redo log)
Q: 4 种隔离级别?
| 级别 | 脏读 | 不可重复读 | 幻读 |
|---|---|---|---|
| READ UNCOMMITTED | ✗ | ✗ | ✗ |
| READ COMMITTED | ✓ | ✗ | ✗ |
| REPEATABLE READ(InnoDB 默认) | ✓ | ✓ | ✓(间隙锁) |
| SERIALIZABLE | ✓ | ✓ | ✓ |
Q: MVCC 是什么?
多版本并发控制。每行有 trx_id 和 roll_ptr,读时按 ReadView 找对自己可见的版本。实现 RC/RR 两种隔离级别下的非阻塞读。
Q: 当前读 vs 快照读?
- 快照读:普通
SELECT,走 MVCC 历史版本 - 当前读:
SELECT ... FOR UPDATE/LOCK IN SHARE MODE/ 所有写操作,加锁读最新
三、锁
Q: InnoDB 锁类型?
| 锁 | 说明 |
|---|---|
| 共享锁 S / 排他锁 X | 读锁 / 写锁 |
| 行锁 | 锁单行 |
| 间隙锁 (Gap Lock) | 锁两行之间的”缝”,防幻读 |
| 临键锁 (Next-Key) | 行锁 + 间隙锁,RR 隔离级别默认加它 |
| 意向锁 IS/IX | 表级,标记”我打算在某行加 S/X 锁” |
Q: 死锁怎么排查?
1 | SHOW ENGINE INNODB STATUS; -- 看 LATEST DETECTED DEADLOCK |
Q: 死锁怎么避免?
- 多个事务以相同顺序访问表/行
- 事务保持短小
- 用低隔离级别(RC 不加间隙锁)
- 给热点资源建索引(避免锁升级到表锁)
四、SQL 优化
Q: EXPLAIN 重点看哪几列?
type:访问类型,从好到差system > const > eq_ref > ref > range > index > ALLkey:实际用到的索引rows:预估扫描行数Extra:Using index(覆盖)/Using filesort(额外排序,差)/Using temporary(临时表,差)
Q: 慢 SQL 怎么排查?
- 开慢查询日志
slow_query_log = 1 - 用
mysqldumpslow/pt-query-digest聚合 - 单条
EXPLAIN/EXPLAIN ANALYZE SHOW PROFILE看每阶段耗时
Q: LIMIT 100000, 20 怎么优化?
延迟关联:先用覆盖索引拿 20 个 id,再 join 主表。详见 覆盖索引。
Q: COUNT(*) vs COUNT(1) vs COUNT(列)?
COUNT(*)/COUNT(1)等价,统计行数(含 NULL)COUNT(列)不统计 NULL- InnoDB 都需要扫描,没有 MyISAM 那种缓存
五、存储引擎
Q: MyISAM vs InnoDB?
| 维度 | MyISAM | InnoDB |
|---|---|---|
| 事务 | ✗ | ✓ |
| 行锁 | ✗(表锁) | ✓ |
| 外键 | ✗ | ✓ |
| 崩溃恢复 | 弱 | 强(redo log) |
| COUNT(*) | 缓存,O(1) | 需扫描 |
| 全文索引 | ✓ | 5.6+ ✓ |
结论:除非纯只读统计场景,永远用 InnoDB。
六、主从复制 & 高可用
Q: 主从复制原理?
- 主库写入 binlog
- 从库 IO 线程拉取 binlog → 写 relay log
- 从库 SQL 线程回放 relay log
Q: 主从延迟怎么解决?
- 大事务拆小
- 从库开并行复制 (
slave_parallel_workers) - 关键读走主库(”读己写”场景)
- 上 ProxySQL / 中间件路由
Q: binlog 三种格式?
STATEMENT:记 SQL,体积小但函数/触发器主从结果可能不一致ROW:记每行变化,安全推荐,体积大MIXED:自动二选一
七、其它高频
Q: redo log 和 binlog 区别?
- redo log:InnoDB 引擎层,物理日志(”在某页改某字节”),循环写
- binlog:Server 层,逻辑日志,追加写,用于复制和恢复
Q: 一条 SQL 的执行流程?
连接器 → 查询缓存(8.0 移除)→ 分析器(词法/语法)→ 优化器(选索引、决定 join 顺序)→ 执行器 → 存储引擎
Q: 表设计三范式?
1NF:字段不可再分;2NF:非主键完全依赖主键;3NF:非主键不传递依赖。实际开发常反范式(冗余字段)换性能。
配图


进一步阅读
- MySQL 数据类型选型
- 覆盖索引
- 索引优缺点
- 索引失效 12 种原因
- 《高性能 MySQL》第 3、4、5、6 章



