一、索引:为什么用 B+ 树
MySQL InnoDB 默认用 B+ 树索引:矮胖结构让三层就能存千万级数据,查询稳定 O(log n);叶子节点用双向链表相连,范围查询极快;非叶子节点只存键,单页能放更多分支。哈希索引等值快但不支持范围和排序,所以不是默认。
| 概念 | 说明 |
|---|---|
| 回表 | 二级索引查到主键后再去聚簇索引取整行 |
| 覆盖索引 | 查询字段都在索引里,不用回表,最快 |
| 最左前缀 | 联合索引 (a,b,c) 只从左列开始命中 |
二、事务与隔离级别
ACID:原子性、一致性、隔离性、持久性。隔离级别解决三类并发问题:
| 级别 | 脏读 | 不可重复读 | 幻读 |
|---|---|---|---|
| 读未提交 | 可能 | 可能 | 可能 |
| 读已提交 | 否 | 可能 | 可能 |
| 可重复读(默认) | 否 | 否 | 基本避免 |
| 串行化 | 否 | 否 | 否 |
InnoDB 在可重复读下靠 MVCC + 间隙锁 基本杜绝幻读。
三、锁
- 行锁:基于索引加锁,没走索引会升级为表锁;
- 间隙锁:锁住索引区间,防插入导致幻读;
- 死锁:两个事务交叉持有对方要的锁,InnoDB 检测后回滚代价小的一方。
四、慢查询优化思路
- 用
EXPLAIN看是否走索引、是否 filesort; - 避免
SELECT *和索引列上做函数运算; - 大表分页用游标(where id > last_id limit n)替代 offset 深翻;
- 该加的联合索引按”高频 + 区分度”排序列顺序。
数据库面试题考的就是”为什么”:为什么 B+ 树、为什么最左前缀、隔离级别怎么实现的——讲清机制与代价就过关。