InnoDB 是 MySQL 默认的事务型存储引擎,它的底层可以从 存储结构、索引、事务、锁、MVCC、日志与崩溃恢复 六大块来理解。
一句话总览:
InnoDB = 基于 B+Tree 的聚簇索引存储 + WAL(日志先行) + MVCC 多版本并发控制 + 行级锁 + Redo/Undo 崩溃恢复机制。
下面按架构拆开讲。
一、数据存储结构:表即 B+Tree(聚簇索引)
1. 聚簇索引(Clustered Index)
InnoDB 表的数据本身就是一棵 B+Tree:
- 叶子节点存放:整行数据
- 按主键顺序组织
- 一张表只能有一个聚簇索引(通常是主键)
B+Tree(主键)
├─ page (16KB)
│ ├─ 行记录1
│ ├─ 行记录2
2. 二级索引
二级索引也是 B+Tree,但叶子节点存的是:
(二级索引值, 主键值)
查询流程:
二级索引 → 找到主键 → 回表 → 聚簇索引取整行
二、页与缓冲池(Buffer Pool)
- InnoDB 最小 IO 单位:Page(16KB)
- 核心内存结构:Buffer Pool
- 热数据在内存,冷数据从磁盘加载
- 采用 LRU + Free List 管理
所有读写都先操作内存页,再异步刷盘。
三、事务与 ACID 的实现
1. Redo Log(保证持久性 D)
- 物理日志(页修改记录)
- 顺序写(WAL)
- 崩溃恢复时重放 Redo
流程:
修改内存页 → 写 Redo Log → 提交事务 → 后台刷脏页
2. Undo Log(保证原子性 A + MVCC)
-
逻辑日志(反向操作)
-
用于:
- 回滚事务
- 构造历史版本(快照读)
四、MVCC:多版本并发控制(保证一致性 C)
每行记录有隐藏字段:
trx_id:最近修改该行的事务IDroll_pointer:指向 Undo Log 版本链
读操作流程:
Read View(事务快照)
↓
顺着 Undo 链找可见版本
实现效果:
- 读不阻塞写
- 写不阻塞读
- 支持 RC / RR 隔离级别
五、锁机制:行锁 + 间隙锁
InnoDB 的锁是基于 索引记录 的:
1. 行锁(Record Lock)
锁住某条索引记录
2. 间隙锁(Gap Lock)
锁住索引区间,防止幻读
3. Next-Key Lock
Record Lock + Gap Lock
RR 隔离级别下防止:
SELECT ... FOR UPDATE
出现幻读。
六、两阶段提交(保证 Redo 与 Binlog 一致)
事务提交流程:
1. 写 Redo Log (prepare)
2. 写 Binlog
3. Redo Log commit
崩溃恢复:
- 有 prepare + binlog → 提交
- 只有 prepare → 回滚
七、崩溃恢复流程
启动时:
- 扫描 Redo Log
- 重做已提交但未刷盘的数据
- 回滚未提交事务(Undo)
八、为什么 InnoDB 适合 OLTP?
因为它具备:
| 能力 | 原理 |
|---|---|
| 高并发 | 行锁 + MVCC |
| 高性能 | Buffer Pool + B+Tree |
| 强事务 | Redo + Undo |
| 不丢数据 | WAL + 两阶段提交 |
| 可恢复 | 崩溃恢复机制 |
面试级一句话总结
InnoDB 以主键聚簇 B+Tree 组织数据,通过 Buffer Pool 缓存页,使用 Redo Log 实现 WAL 保证持久性,用 Undo Log + Read View 实现 MVCC 多版本并发控制,采用行锁、间隙锁防止并发冲突,并通过两阶段提交保证 Redo 与 Binlog 一致性,从而完整实现 ACID 事务特性。