找回密码
立即注册
搜索
热搜: Java Python Linux Go
发回帖 发新帖

155

积分

0

好友

19

主题
发表于 4 天前 | 查看: 7| 回复: 0

图片

MySQL在崩溃后如何恢复数据?为什么更新操作不立即写入磁盘?主从复制为何依赖binlog而非redo log?本文将通过流程图详解InnoDB的三大日志系统。

三大日志的核心职责

  • Redo Log(重做日志):保证事务的持久性,确保已提交的事务不会丢失
  • Undo Log(回滚日志):负责事务回滚,MVCC一致性读依赖undo生成的行版本
  • Bin Log(二进制日志):实现主从复制和数据恢复功能

详细操作流程

1. 读取磁盘页到Buffer Pool

执行SQL语句时:

UPDATE user SET age = 30 WHERE id = 1;

MySQL的InnoDB存储引擎首先会:

  • 判断所需数据页是否在buffer pool中
  • 如果不在,则从磁盘加载数据页到buffer pool

2. 生成undo log(记录旧值)

在更新数据前,InnoDB会将旧记录写入undo log:

  • 用于事务回滚操作
  • 支持MVCC隔离级别的一致性读

3. 修改Buffer Pool中的数据(内存更新)

InnoDB不会立即修改磁盘文件,而是:

  • 直接修改内存中的数据页
  • 修改后的内存页变为脏页(dirty page)

4. 记录redo log(写入redo log buffer)

同时,InnoDB会将“对哪页做了什么修改”的信息写入redo log buffer。

至此,数据已经:

  • 在内存(Buffer Pool)中完成修改
  • 写入redo log buffer
  • 但磁盘文件尚未更新

5. redo log刷盘(prepare阶段)

在事务即将提交时,InnoDB执行:

  • 将redo log buffer写入磁盘的redo log文件
  • 写入状态标记为:prepare

这一步标志着redo log已支持该事务恢复,但事务尚未完全提交。

6. 写binlog(记录事务逻辑)

MySQL Server层开始记录binlog:

  • 写入binlog buffer
  • 刷盘到binlog文件

7. 事务提交(commit)并写入binlog位点

binlog落盘成功后:

  • 在redo log中写入commit标记

这一步完成“两阶段提交”,确保数据恢复时redo log与binlog的一致性。

后续处理流程

上面的流程仅保证:

  • undo log已写入
  • redo log已写入
  • binlog已写入
  • 内存数据已修改

但磁盘数据文件此时仍未被真正修改。

后台线程会执行以下操作:

8. IO线程异步刷脏页

后台LRU和flush线程将:

  • 把Buffer Pool中的脏数据页写回磁盘
  • 此过程为异步操作,不阻塞事务提交

9. 刷盘数据文件(持久化真实数据)

最终磁盘文件才真正完成数据变更的持久化。

您需要登录后才可以回帖 登录 | 立即注册

手机版|小黑屋|网站地图|云栈社区(YunPan.Plus) ( 苏ICP备2022046150号-2 )

GMT+8, 2025-12-1 17:05 , Processed in 0.059651 second(s), 39 queries , Gzip On.

Powered by Discuz! X3.5

© 2025-2025 CloudStack.

快速回复 返回顶部 返回列表