MySQL的InnoDB的底层原理

36 阅读3分钟

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:最近修改该行的事务ID
  • roll_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 → 回滚

七、崩溃恢复流程

启动时:

  1. 扫描 Redo Log
  2. 重做已提交但未刷盘的数据
  3. 回滚未提交事务(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 事务特性。