InnoDB 存储结构
InnoDB 是 MySQL 默认的通用事务引擎。它以表空间中的 Page 保存 B+ Tree,通过 Buffer Pool 缓存数据,使用 Redo/Undo、Doublewrite 和 Checkpoint 保证事务与崩溃恢复。
内存与磁盘
| 结构 | 作用 |
|---|---|
| Buffer Pool | 缓存表和索引页,是主要数据库缓存 |
| Log Buffer | 暂存 Redo Record,按提交和后台策略写出 |
| System Tablespace | 保存系统级 InnoDB 数据,具体内容随版本和配置变化 |
| File-Per-Table Tablespace | 通常每张表一个 .ibd,保存聚集和二级索引 |
| Undo Tablespace | 保存 Undo Log,支持回滚和 MVCC |
| Temporary Tablespace | 保存 InnoDB 临时表和执行中间数据 |
| Redo Log | 顺序记录页变化,支持崩溃恢复 |
页、区、段和表空间
Tablespace
└── Segment
└── Extent
└── Page
└── RecordPage 是 Buffer Pool 与磁盘交互的主要单位。B+ Tree 的叶子和非叶子节点都由 Page 组成;顺序主键通常让新行集中追加到右侧叶子,随机主键更容易产生随机 I/O、Page Split 和较差缓存局部性。
这不意味着所有系统都必须使用自增主键。分布式 ID、热点写入、业务排序和安全暴露仍需权衡;关键是理解主键会成为聚集索引,并复制进每个二级索引条目。
Redo、Undo 与 Binlog
| 日志 | 所属层 | 作用 |
|---|---|---|
| Redo Log | InnoDB | 重放已提交但未完整写入数据文件的页变化 |
| Undo Log | InnoDB | 回滚事务并向 Read View 提供旧版本 |
| Binary Log | MySQL Server | 复制、CDC 和时间点恢复 |
| Error Log | MySQL Server | 运行与诊断事件,不用于数据恢复 |
事务提交时,InnoDB Redo 与 Server Binlog 通过内部协调保持一致。调整 innodb_flush_log_at_trx_commit 或 sync_binlog 会改变性能和故障损失窗口,不能只按吞吐调低。
Checkpoint 与 Doublewrite
Checkpoint 推进脏页写回,使 Redo 空间可以循环复用并限制恢复工作量。脏页写回数据文件前,Doublewrite 会先保存可恢复副本,用于处理断电或存储异常造成的 Torn Page。
Doublewrite 不是数据双副本,也不能防止整盘损坏。Redo、Doublewrite、Replica 和 Backup 分别覆盖不同故障。
Undo、History 与 Purge
UPDATE/DELETE 产生的旧版本可能仍被活跃 Read View 读取,事务提交后不能立刻清除。Purge 线程在确认不再需要后回收历史版本。
长事务会导致:
- Undo History 增长,Purge 无法推进。
- 旧版本查询链变长。
- 删除空间不能及时复用。
- DDL、备份和复制延迟风险增加。
监控 InnoDB 时必须同时观察长事务、History List、Buffer Pool、Redo/Checkpoint 和 I/O,而不是只看慢 SQL。