InnoDB 组成
InnoDB 组成

内存结构 :
- Buffer Pool
- AHI
- Log Buffer
- Change Buffer
硬盘结构:
- TableSpace
- Redo Log
- UnDo Log
Buffer Pool
是内存中一块连续的区域,用于缓存表和索引的数据. 用于加速数据访问与读写.
Page
buffer pool 中存放着 许多 page, 每个 page 记录着表中的数据行(rows)、索引条目(index entries)大小为16kb. page 中存放的不是整张表 而是多行数据.
当进行 SQL 查找时(如 SELECT 查询),InnoDB 会:
- 通过主键或索引定位到具体的 page(由空间 ID + 页号标识)。
- 检查 Buffer Pool 中是否已有该 page(命中率高时,直接从内存返回数据)。
- 如果未命中,从磁盘(.ibd 文件)加载整个 16KB page 到 Buffer Pool。
- 返回所需数据行,同时将该 page 标记为“活跃”,以便后续快速访问。
存储方式
- 每个 page 被连接成双向循环链表,并分为两块区域.
- 使用 LRU(Least Recently Used,最近最少使用)算法的变体来淘汰不常用的页面.
- 新子列表(young sublist)(最近访问的页面)和旧子列表(old sublist)(较少访问的页面)。
- 中点(midpoint):young 和 old 的分界线。新加载的 page 先插入中点(old 的头部),观察其是否被访问。

AHI
InnoDB 的自适应哈希索引,是一个内置在 Buffer Pool 中的内存哈希表,用于加速等值查找
作用
- 加速查询:对于频繁的精确匹配查询,哈希表提供 O(1) 访问速度,比 B+ 树索引的 O(log n) 更快。
- 动态构建:InnoDB 根据实际查询模式自动创建/删除哈希条目,无需手动配置。
- 适用场景:读密集型工作负载,尤其是点查询(point queries),如主键查找或唯一索引等值条件。
日志系统
InnoDB 的事务恢复基于 WAL 技术,采用 NO-FORCE + STEAL 策略,通过 Redo Log(重做)与 Undo Log(回滚)来保障事务的持久性与原子性。
Log Buffer
Log Buffer(又称 redo log buffer)是 InnoDB 在内存中用于暂存 redo log 记录的区域。当事务修改 Buffer Pool 中的数据页时,InnoDB 会同时生成对应的 redo log(描述该物理修改),并写入 log buffer。随后,这些 redo log 会根据策略(如事务提交、超时或缓冲区满)被刷入磁盘的 redo log 文件。若数据库崩溃,InnoDB 可在重启时通过重放已持久化的 redo log,恢复那些已提交但尚未写入数据文件的更改,从而保证事务的持久性。
Redo Log
Redo log 是存储在磁盘上的物理日志,用于在数据库崩溃后恢复已提交事务的持久化状态。它以面向存储页的方式记录修改,内容类似于“在表空间某页的偏移 Y 处写入 Z”。崩溃恢复时,InnoDB 先重做所有 redo log 记录,再通过 undo log 回滚未提交的事务,从而保证 ACID。
Redo Log 是 WAL(Write-Ahead Logging)技术的核心:修改先写日志,再写数据文件,减少随机 I/O,提高性能。
崩溃恢复时 InnoDB:
- 重做所有已提交但未持久化的记录
- 通过undo log 将 buffer pool 中未提交的事务回滚
Undo Log
Undo Log 记录了事务对数据修改的“反向操作”,允许其他事务读取未修改的旧版本数据(一致性读),并在事务回滚时恢复数据。他保存了数据的“历史快照”,确保事务的 ACID 属性(原子性、一致性、隔离性、持久性)。
Undo Log 主要用于:
- MVCC:事务间隔离读,避免锁竞争。
- 回滚:事务失败时撤销修改。
- 崩溃恢复:虽不直接用于恢复,但辅助 purge 操作清理旧数据。
Undo Log 分为两类:用户表(regular tables)的 Undo Log(需 redo 日志保护,用于崩溃恢复)和临时表(temporary tables)的 Undo Log(仅用于运行时回滚,不生成 redo 日志,提高性能)。
表空间(Tablespaces):Undo Log 存储在独立的 Undo Tablespaces(最多 128 个回滚段/表空间)和全局临时表空间(temp tablespace)。每个事务最多分配 4 个 Undo Log(分别处理用户表的 INSERT、UPDATE/DELETE 和临时表的 INSERT、UPDATE/DELETE)。
Change Buffer

属于 Buffer Pool 的一块内存结构,存储着**二级索引(非主索引)发生的变更,当二级索引发生更新时如果受影响的二级索引页面不在 Buffer Pool 中,**不会立即更新到磁盘中,而是先存储到 Change Buffer 当这个页面因为其他读操作被加载到 Buffer Pool 时,这些变更才会“合并”(merge)进去.