MySQL 面试专题:高频考点深度解析

在这里插入图片描述

面试中 MySQL 是必考点,既考察基础(索引、事务),也会深挖原理(B+ 树、锁机制、执行计划)。
下面我们从 高频面试问题 出发,逐个拆解,并提供 答案思路 + 深入细节 + 扩展提问


一、索引相关

1. 为什么 InnoDB 使用 B+ 树而不是 B 树 / 哈希索引?

答题思路:

  • B 树存储数据在每个节点,非叶子节点也存数据,可能导致一次磁盘 IO 拿不到完整范围数据。
  • B+ 树只在叶子节点存储数据,非叶子节点只存索引,层数更少,磁盘 IO 更少。
  • B+ 树叶子节点之间有链表,适合范围查询。
  • 哈希索引适合点查,不支持范围查询和排序。

扩展问法:

  • 如果主键是自增 ID 和 UUID,B+ 树索引的存储区别是什么?
    👉 自增 ID 插入有序,B+ 树分裂少;UUID 随机,会导致页分裂和碎片,性能差。

2. 联合索引的最左前缀原则是什么?

答题思路:

  • 假设索引 (a, b, c),可以用到 (a)(a, b)(a, b, c),也能用 (a, c) 吗?答案是 不能
  • 因为索引是按照最左字段依次排序的,必须连续匹配。

扩展问法:

  • 如果有 WHERE a=1 AND c=2,会用到索引吗?
    👉 可以用到 a,但 c 不能用到索引,需要额外过滤。

3. 覆盖索引是什么?

答题思路:

  • 覆盖索引 = 查询所需字段都在索引里,不需要回表。
  • 优点:减少一次回表 IO,提高查询性能。

举例:

SELECT id, name FROM users WHERE id = 100;

如果有索引 (id, name),直接从索引里拿,不需要再回到表里。


二、事务与锁

1. 事务的四大特性(ACID)是什么?

  • A(原子性):事务要么全部成功,要么全部失败(undo log 保证)。
  • C(一致性):事务前后数据满足约束条件。
  • I(隔离性):事务之间互不干扰。
  • D(持久性):事务提交的数据会持久保存(redo log 保证)。

扩展问法:

  • MySQL 是如何保证原子性和持久性的?
    👉 undo log 保证原子性,redo log + binlog 保证持久性。

2. MySQL 的事务隔离级别有哪些?

  • 读未提交(RU):可能读到未提交数据(脏读)。
  • 读已提交(RC):避免脏读,但可能不可重复读。
  • 可重复读(RR,InnoDB 默认):避免脏读 + 不可重复读,但可能幻读。
  • 串行化(Serializable):强制事务串行执行,性能差。

扩展问法:

  • InnoDB 在 RR 下是如何避免幻读的?
    👉 MVCC + Next-Key Lock(间隙锁)。

3. 行锁和表锁的区别?

  • 行锁:粒度小,冲突少,开销大。InnoDB 支持。
  • 表锁:粒度大,冲突多,开销小。MyISAM 使用。

扩展问法:

  • 什么时候 InnoDB 也会锁全表?
    👉 没有索引时,UPDATE/DELETE 会退化成全表锁。

三、执行计划与优化

1. EXPLAIN 输出中 type 字段的含义?

  • const:常量查询,效率最高。
  • eq_ref:唯一索引等值连接。
  • ref:非唯一索引等值。
  • range:范围查询。
  • index:全索引扫描。
  • ALL:全表扫描,最差。

👉 面试高频:如何优化 ALL?

  • 建索引
  • 改写 SQL
  • 分库分表

2. Extra 字段里出现 Using filesort / Using temporary 怎么办?

  • Using filesort:说明排序没用到索引,可以用 索引优化 order by
  • Using temporary:说明 group by 用了临时表,可以用 索引优化 group by物化视图

四、日志与存储

1. redo log 和 binlog 的区别?

  • redo log(InnoDB 特有):物理日志,记录数据页的修改,用于 crash recovery。
  • binlog(Server 层):逻辑日志,记录 SQL 语句或行变更,用于主从复制和数据恢复。

两阶段提交保证一致性:

  1. 写 redo log (prepare)
  2. 写 binlog
  3. redo log (commit)

2. undo log 的作用?

  • 提供回滚(保证原子性)。
  • 提供多版本快照(MVCC,保证一致性和隔离性)。

五、综合案例:面试常见 SQL 优化题

题目:
有一张 orders 表(千万级数据),字段如下:

id (PK)
customer_id
status
order_date
amount

请优化以下 SQL:

SELECT * FROM orders WHERE status = 1 AND order_date > '2023-01-01' ORDER BY order_date;

思路:

  1. 加复合索引 (status, order_date)
  2. 如果查询字段很少,可以用覆盖索引 (status, order_date, amount)
  3. 如果只取最近数据,加 LIMIT 减少结果集。
  4. 避免 SELECT *,只取需要字段。

六、总结:面试回答套路

  1. 先说结论(简单直白)
  2. 再讲原理(深入解释)
  3. 最后扩展(举例 + 面试官可能追问的方向)

👉 面试官常问的问题几乎都围绕:

  • 索引(B+ 树、最左前缀、覆盖索引)
  • 事务(ACID、MVCC、锁)
  • 执行计划(EXPLAIN)
  • 日志(redo、undo、binlog)
  • SQL 优化案例

Logo

有“AI”的1024 = 2048,欢迎大家加入2048 AI社区

更多推荐