Innodb是如何实现事务的
以下是 InnoDB 通过 Buffer Pool、Log Buffer、Redo Log、Undo Log 实现事务(以 UPDATE 为例)的核心机制总结:
1. Buffer Pool(缓冲池)
- 作用:内存缓存区,缓存磁盘中的表/索引数据页(
Page)。 - UPDATE 流程:
- 从磁盘读取目标数据页到 Buffer Pool(若不存在)。
- 在 Buffer Pool 中修改数据页内容(此时页变为 脏页 Dirty Page)。
- 延迟写入磁盘:脏页不会立即刷盘,由后台线程异步处理(提高性能)。
2. Undo Log(回滚日志)
- 作用:
- 回滚:记录数据修改前的值,用于事务回滚(
ROLLBACK)。 - MVCC:构建多版本数据链,支持非锁定读(
SELECT读取旧版本)。
- 回滚:记录数据修改前的值,用于事务回滚(
- UPDATE 流程:
- 修改数据前,将旧值写入 Undo Log(生成回滚记录)。
- 若事务回滚,则用 Undo Log 恢复原始数据。
- 事务提交后,Undo Log 不会立即删除(可能被其他事务的 MVCC 读引用)。
3. Redo Log(重做日志)
- 作用:保证事务的 持久性(Durability)。
- 记录数据页的 物理修改(如
Page ID、偏移量、修改值)。 - 崩溃恢复时重放未落盘的修改。
- 记录数据页的 物理修改(如
- UPDATE 流程:
- 修改 Buffer Pool 数据页前,生成 Redo Log 记录。
- Redo Log 暂存于内存的 Log Buffer。
- 事务提交时,Log Buffer 按策略刷盘(
innodb_flush_log_at_trx_commit控制):=1:同步写磁盘(确保不丢失)。=0/2:延迟写(性能更高,但可能丢失部分数据)。
4. Log Buffer(日志缓冲区)
- 作用:Redo Log 的临时内存缓冲区。
- UPDATE 流程:
- Redo Log 记录先写入 Log Buffer。
- 事务提交时触发刷盘(由参数控制策略)。
- 避免每次修改都写磁盘,提升性能。
UPDATE 操作完整流程
崩溃恢复机制
- Redo Log 重做:
- 重放已提交事务的 Redo Log,恢复 Buffer Pool 中的脏页。
- Undo Log 回滚:
- 对未提交的事务,用 Undo Log 回滚修改。
关键设计思想
- Write-Ahead Logging (WAL):
Redo Log 先于数据页落盘(确保持久性)。 - 随机写转顺序写:
数据页修改(随机写) → Redo Log 追加(顺序写),大幅提升 IO 效率。 - 异步刷脏页:
事务提交只需保证 Redo Log 落盘,脏页由后台线程批量写入磁盘。 - 两阶段提交(2PC):
与 Binlog 协作时,通过 Redo Log 的prepare和commit状态保证一致性。
核心组件对比
| 组件 | 作用 | 持久化时机 | 是否崩溃恢复必需 |
|---|---|---|---|
| Buffer Pool | 缓存数据页 | 异步刷脏页 | ❌ |
| Log Buffer | 缓存 Redo Log | 事务提交时控制刷盘 | ❌ |
| Redo Log | 保证事务持久性 | 事务提交时强制刷盘 | ✔️ |
| Undo Log | 支持回滚与 MVCC | 随 Redo Log 间接持久化 | ✔️ |
关键结论:
- 提交性能:由 Redo Log 刷盘效率决定(顺序写远快于随机写)。
- 数据安全:事务提交后即使脏页未落盘,Redo Log 也能保证数据不丢失。
- 回滚能力:Undo Log 使得任意时刻回滚成为可能。