MySQL 面试题
2026/1/15大约 5 分钟
MySQL 面试题
索引相关
1. 什么是索引?为什么要用索引?
索引是帮助 MySQL 高效获取数据的数据结构。
优点:
- 提高查询效率
- 加速排序和分组
缺点:
- 占用磁盘空间
- 降低写入性能
2. MySQL 索引使用什么数据结构?
B+ 树。
B+ 树的特点:
- 非叶子节点只存索引,不存数据
- 叶子节点存储所有数据,通过指针连接
- 查询效率稳定,都是 O(logN)
3. 为什么用 B+ 树而不是 B 树?
- B+ 树非叶子节点不存数据,可以存更多索引,树更矮
- B+ 树叶子节点有链表,范围查询更高效
- B+ 树查询效率稳定
4. 什么是聚簇索引和非聚簇索引?
- 聚簇索引:叶子节点存储完整行数据,一个表只能有一个
- 非聚簇索引:叶子节点存储主键值,需要回表查询
5. 什么是回表?如何避免?
回表是指通过非聚簇索引查询时,需要再根据主键到聚簇索引查询完整数据。
避免方法:使用覆盖索引,查询的字段都在索引中。
6. 什么是最左前缀原则?
联合索引 (a, b, c) 只有在查询条件包含 a 时才能使用索引。
-- 能使用索引
WHERE a = 1
WHERE a = 1 AND b = 2
WHERE a = 1 AND b = 2 AND c = 3
-- 不能使用索引
WHERE b = 2
WHERE c = 37. 索引失效的场景有哪些?
- 对索引列使用函数
- 对索引列进行运算
- 类型隐式转换
- LIKE 以 % 开头
- OR 条件(部分列无索引)
- 不满足最左前缀原则
事务相关
8. 什么是事务?ACID 是什么?
事务是一组操作的集合,要么全部成功,要么全部失败。
- A(原子性):事务不可分割
- C(一致性):数据状态一致
- I(隔离性):事务互不干扰
- D(持久性):提交后永久保存
9. 事务隔离级别有哪些?
| 隔离级别 | 脏读 | 不可重复读 | 幻读 |
|---|---|---|---|
| READ UNCOMMITTED | ✓ | ✓ | ✓ |
| READ COMMITTED | ✗ | ✓ | ✓ |
| REPEATABLE READ | ✗ | ✗ | ✓ |
| SERIALIZABLE | ✗ | ✗ | ✗ |
MySQL 默认是 REPEATABLE READ。
10. 什么是脏读、不可重复读、幻读?
- 脏读:读到其他事务未提交的数据
- 不可重复读:同一事务内两次读取结果不同(数据被修改)
- 幻读:同一事务内两次读取结果不同(数据被插入/删除)
11. MVCC 是什么?
多版本并发控制,通过保存数据的历史版本,实现非阻塞读。
核心组件:
- 隐藏列(trx_id、roll_pointer)
- undo log(历史版本)
- Read View(可见性判断)
12. redo log 和 undo log 的区别?
| 特性 | redo log | undo log |
|---|---|---|
| 作用 | 保证持久性 | 保证原子性 |
| 内容 | 物理日志(页的修改) | 逻辑日志(反向操作) |
| 写入时机 | 事务执行中 | 事务执行中 |
| 用途 | 崩溃恢复 | 事务回滚、MVCC |
13. redo log 和 binlog 的区别?
| 特性 | redo log | binlog |
|---|---|---|
| 层级 | InnoDB 引擎 | Server 层 |
| 内容 | 物理日志 | 逻辑日志 |
| 写入方式 | 循环写 | 追加写 |
| 用途 | 崩溃恢复 | 主从复制、数据恢复 |
锁相关
14. MySQL 有哪些锁?
按粒度:
- 全局锁
- 表级锁
- 行级锁
按模式:
- 共享锁(S锁)
- 排他锁(X锁)
行锁类型:
- 记录锁
- 间隙锁
- 临键锁
15. 什么是间隙锁?
锁定索引记录之间的间隙,防止其他事务插入数据,解决幻读问题。
16. 什么是死锁?如何避免?
两个或多个事务互相等待对方持有的锁。
避免方法:
- 固定加锁顺序
- 减少锁持有时间
- 降低隔离级别
- 使用合理的索引
17. 乐观锁和悲观锁的区别?
- 悲观锁:假设会冲突,先加锁再操作(FOR UPDATE)
- 乐观锁:假设不冲突,通过版本号检测冲突
优化相关
18. 如何优化慢查询?
- 开启慢查询日志
- 使用 EXPLAIN 分析执行计划
- 优化索引
- 优化 SQL 语句
- 优化表结构
19. EXPLAIN 中 type 字段的含义?
性能从好到差:
- system/const:常量查询
- eq_ref:主键关联
- ref:非唯一索引
- range:范围查询
- index:全索引扫描
- ALL:全表扫描
20. 如何优化深分页?
-- 问题
SELECT * FROM t LIMIT 1000000, 10;
-- 方案1:使用主键
SELECT * FROM t WHERE id > 1000000 LIMIT 10;
-- 方案2:延迟关联
SELECT * FROM t INNER JOIN (SELECT id FROM t LIMIT 1000000, 10) tmp ON t.id = tmp.id;21. COUNT(*) 和 COUNT(1) 哪个快?
性能相同。COUNT(*) 和 COUNT(1) 都是统计行数,MySQL 会自动优化。
COUNT(column) 不统计 NULL 值。
其他
22. InnoDB 和 MyISAM 的区别?
| 特性 | InnoDB | MyISAM |
|---|---|---|
| 事务 | 支持 | 不支持 |
| 行级锁 | 支持 | 不支持 |
| 外键 | 支持 | 不支持 |
| 崩溃恢复 | 支持 | 不支持 |
| 全文索引 | 5.6+ 支持 | 支持 |
23. 什么是主从复制?
将主库的数据同步到从库。
过程:
- 主库写 binlog
- 从库 IO 线程读取 binlog,写入 relay log
- 从库 SQL 线程执行 relay log
24. 主从延迟怎么解决?
- 使用并行复制
- 优化主库性能
- 读写分离时,强一致性读走主库
25. 分库分表怎么做?
垂直拆分:
- 垂直分库:按业务拆分
- 垂直分表:将大字段拆分到另一张表
水平拆分:
- 水平分库:按某个字段分库
- 水平分表:按某个字段分表
分片策略:
- 范围分片
- Hash 分片
- 一致性 Hash
26. 如何保证数据不丢失?
- 设置
innodb_flush_log_at_trx_commit = 1 - 设置
sync_binlog = 1 - 使用主从复制
- 定期备份