MySQL-Redo Log(重做日志)

MySQL 的 Redo Log(重做日志)是 InnoDB 存储引擎的核心组件之一,是保证数据库持久性(Durability)崩溃恢复(Crash Recovery) 的关键机制。


1. 什么是 Redo Log?它的核心作用是什么?

核心作用: 保证事务的持久性(Durability)

这意味着,只要一个事务成功提交(COMMIT),那么它对数据库所做的修改就绝对不会丢失,即使随后发生数据库宕机、断电等故障,在重启后也能通过 Redo Log 恢复这些已提交的修改。

简单比喻:

想象一下一家生意火爆的餐馆。

  • 磁盘上的数据文件(.ibd):就像后厨的正式账本,记录着所有订单的最终状态。但每做一笔都直接记上去,效率太低。

  • Buffer Pool(内存缓冲池):就像服务员手里的点餐小票,记录了最新的订单。读写速度快,但一撕就丢(掉电丢失)。

  • Redo Log :就像服务员飞速记在黑板上的订单。客人下单(事务提交)后,服务员会立刻先把订单写到黑板上,然后再慢慢交给后厨处理。即使后厨还没来得及把菜做完(数据没刷盘)或者服务员手里的小票丢了(内存丢失),只要黑板上的字还在,就能知道客人点了什么,确保订单不会丢失。

这个"先写黑板,再慢慢处理"的过程,就是著名的 Write-Ahead Logging (WAL) 技术,而 Redo Log 就是实现 WAL 的载体。


2. 为什么需要 Redo Log?------ 解决性能问题

如果没有 Redo Log,为了保证持久性,InnoDB 必须在每次事务提交时,都将该事务修改的所有数据页随机地、同步地刷新到磁盘上。

  • 随机 I/O:数据页在磁盘上分布是零散的,写入是随机写,速度很慢。

  • 同步 I/O:提交操作必须等待所有慢速的磁盘 I/O 完成,用户线程会被阻塞。

这会产生巨大的性能瓶颈,因为磁盘的随机 I/O 速度远低于内存操作和顺序 I/O。

Redo Log 的解决方案:

  1. 顺序 I/O :Redo Log 的记录是追加写入的,是顺序写,速度极快(甚至可以用专门的 SSD 优化)。

  2. 组合写入:多个事务的修改可以合并在一起,一次性写入日志文件,大大减少了磁盘 I/O 次数。

  3. 异步刷盘 :事务提交时,只需要保证 Redo Log 成功写入(顺序写,很快),就可以返回成功。内存中的数据页(脏页)则由后台线程异步地、批量地刷新到磁盘(随机写),这个操作不会阻塞用户请求。

所以,Redo Log 通过将随机写转换为顺序写,极大地提升了数据库的写入性能,同时保证了事务的持久性。


3. Redo Log 的组成与工作流程

物理结构

Redo Log 在物理上由两个文件组成,通常命名为 ib_logfile0ib_logfile1。它们被设计成循环写入的固定大小文件。

  • innodb_log_file_size: 每个 Redo Log 文件的大小。

  • innodb_log_files_in_group: Redo Log 文件的数量,默认为 2。

  • 总日志大小 = innodb_log_file_size * innodb_log_files_in_group

逻辑结构

逻辑上,Redo Log 是一个连续的顺序写入空间。为了管理循环写入,它维护了几个关键指针:

  • write pos(写入位置):当前记录写入的位置,随着写入不断后移。

  • checkpoint(检查点):表示已经刷新到磁盘数据文件的位置。它之前的数据已经被持久化,对应的日志空间可以被覆盖。

write poscheckpoint 之间的空间是空闲的可写入部分。当 write pos 追上 checkpoint(即日志文件写满)时,数据库必须停下来,先推进 checkpoint(强制刷脏页),释放出可重用的日志空间,然后才能继续处理新的更新操作。因此,设置过小的 Redo Log 文件会导致频繁的"卡顿"。

工作流程(以 UPDATE 为例)
  1. 数据载入:要修改的数据页如果不在 Buffer Pool 中,则从磁盘加载到 Buffer Pool。

  2. 修改内存:在 Buffer Pool 中修改数据页,使其变成"脏页"。

  3. 写入 Redo Log Buffer :生成一条 Redo Log 记录,描述这个"物理页面"上的修改(如:表空间ID、页号、偏移量、修改后的值等)。这条记录首先被写入到内存中的 Redo Log Buffer

  4. 事务提交 :当用户执行 COMMIT 时,根据 innodb_flush_log_at_trx_commit 的设置,InnoDB 会采取不同的行为将 Redo Log Buffer 中的内容刷新到磁盘的 Redo Log 文件。这是保证持久性的关键步骤。

  5. 刷盘通知:事务提交后,即可返回客户端成功。后台的 I/O 线程会在未来某个时间点将 Buffer Pool 中的"脏页"刷新到磁盘的数据文件中。

  6. 推进 Checkpoint:当脏页被成功刷盘后,对应的 Redo Log 记录就失去了作用(已经持久化了)。Checkpoint 位置就可以向前推进,这部分日志空间可以被后续的写入覆盖。


4. 关键配置参数:innodb_flush_log_at_trx_commit

这个参数控制了事务提交时,刷新 Redo Log 到磁盘的策略,是在性能持久性保证之间进行权衡的关键。

  • = 1 (默认值)

    • 行为 :每次事务提交时,都会将 Redo Log Buffer 的内容同步写入并刷新(fsync) 到磁盘。

    • 保证:最严格的持久性保证。即使宕机,也绝不会丢失任何已提交的事务。

    • 缺点:因为每次提交都要发生一次磁盘 I/O(虽然是顺序的),性能是最差的。

  • = 2

    • 行为 :每次事务提交时,仅将 Redo Log Buffer 的内容写入 到操作系统的页面缓存(Page Cache),但不执行 fsync 刷盘操作。

    • 保证:只有在操作系统不宕机(比如MySQL进程崩溃,但服务器没重启)的情况下,才能保证不丢数据。如果服务器断电,而操作系统缓存中的数据还没来得及刷盘,那么这部分数据就会丢失。

    • 性能 :比 =1 好,因为写入 Page Cache 非常快。

  • = 0

    • 行为 :每秒一次地将 Redo Log Buffer 的内容写入 Page Cache 并调用 fsync 刷到磁盘。事务提交时本身不会触发任何写入。

    • 保证:安全性最差。如果 MySQL 进程崩溃,最多会丢失 1 秒内提交的事务。如果服务器断电,最多可能丢失超过 1 秒的数据(因为还可能有一部分在 Buffer 里没写到 Page Cache)。

    • 性能:最好。

如何选择?

  • 要求绝对数据安全 (如金融交易):必须使用 1

  • 可以容忍丢失极少量数据 (如点赞、评论):可以设置为 2,性能提升显著。

  • 对性能要求极高,且数据不重要 :可考虑 0(一般不推荐)。


5. Redo Log 与 Binlog 的区别

这是一个经典面试题。虽然都是日志,但两者截然不同:

特性 Redo Log Binlog (二进制日志)
归属 InnoDB 引擎层独有的 MySQL Server 层实现的,所有存储引擎都可以使用
类型 物理日志 记录的是"在某个数据页上做了什么修改" 逻辑日志 记录的是语句的原始逻辑(如 UPDATE t SET f1=1)或行变更前后的镜像
写入方式 循环写 文件固定大小,写满会覆盖 追加写 文件写完后会切换到下一个,不会覆盖旧日志
用途 崩溃恢复 (Crash Recovery) 保证事务的持久性 数据归档、主从复制 (Replication) Point-in-Time Recovery(按时间点恢复)

在 MySQL 5.6 引入 两阶段提交(2PC) 之前,需要保证 Redo Log 和 Binlog 的一致性是一个复杂的问题。两阶段提交机制确保了即使发生崩溃,二者也能保持逻辑上的一致。


总结

  • 是什么 :Redo Log 是 InnoDB 的物理日志 ,采用循环写入方式。

  • 为什么 :为了将随机写 转换为顺序写提升写入性能 ,同时保证事务的持久性(WAL 技术的实现)。

  • 怎么做 :事务提交时,先强制写入 Redo Log (取决于 innodb_flush_log_at_trx_commit 设置),再异步刷脏页。

  • 关键点 :通过 write poscheckpoint 管理循环写入,通过配置参数在性能和数据安全间做权衡。

  • 区别 :与 Server 层的逻辑日志 Binlog 在归属、类型、用途上完全不同。

理解 Redo Log 是理解 InnoDB 如何协调高性能与数据安全性的基石。

相关推荐
博睿谷IT99_10 小时前
SQL SELECT 语句怎么用?COMPANY 表查询案例(含条件 / 模糊 / 分页)
数据库·sql·mysql
浅拾光º11 小时前
mysql字符串截取,如何在MySQL备份文件中安全截取敏感字符串?
数据库·mysql·安全
鸠摩智首席音效师11 小时前
如何删除 MySQL 数据库中的所有数据表 ?
数据库·mysql·oracle
Hey! Hey!11 小时前
DBA 系统学习计划(从入门到进阶)
数据库·学习·dba
leo_yu_yty11 小时前
Mysql DBA学习笔记(客户端常用工具)
学习·mysql·dba
没有bug.的程序员11 小时前
SQL 执行计划解析:从 EXPLAIN 到性能优化的完整指南
java·数据库·sql·性能优化·explain·执行计划
qqxhb11 小时前
系统架构设计师备考第30天——关系数据库
数据库·系统架构·数据库设计·关系模式·范式·关系远算·完整性规则
小心草里有鬼12 小时前
Linux 数据库 Mysql8 主从复制
linux·运维·数据库·sql·mysql
chen_note12 小时前
Keepalived两个集群实验
linux·服务器·数据库·keepalived·高可用集群
boy快快长大12 小时前
@Transactional 事务注解
数据库·sql·oracle