【mysql系列】redo log

本文介绍了BufferPool如何提高读写效率,以及InnoDB引擎如何通过WAL技术(Write-AheadLogging)防止断电数据丢失。重点讲解了redolog的作用,它记录事务完成后和开始前的状态,确保事务的持久性和crash-safe特性。还讨论了redolog满时的处理机制,即脏页刷新和checkpoint更新的过程。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

Buffer Pool 是提高了读写效率没错,但是问题来了,Buffer Pool 是基于内存的,而内存总是不可靠,万一断电重启,还没来得及落盘的脏页数据就会丢失。

为了防止断电导致数据丢失的问题,当有一条记录需要更新的时候,InnoDB 引擎就会先更新内存(同时标记为脏页),然后将本次对这个页的修改以 redo log 的形式记录下来,这个时候更新就算完成了。

后续,InnoDB 引擎会在适当的时候,由后台线程将缓存在 Buffer Pool 的脏页刷新到磁盘里,这就是 WAL (Write-Ahead Logging)技术。WAL 技术指的是, MySQL 的写操作并不是立刻写到磁盘上,而是先写日志,然后在合适的时间再写到磁盘上。

什么是 redo log

redo log 是物理日志,记录了某个数据页做了什么修改,比如对 XXX 表空间中的 YYY 数据页 ZZZ 偏移量的地方做了AAA 更新,每当执行一个事务就会产生这样的一条或者多条物理日志。

在事务提交时,只要先将 redo log 持久化到磁盘即可,可以不需要等到将缓存在 Buffer Pool 里的脏页数据持久化到磁盘。

当系统崩溃时,虽然脏页数据没有持久化,但是 redo log 已经持久化,接着 MySQL 重启后,可以根据 redo log 的内容,将所有数据恢复到最新的状态。

被修改 Undo 页面,需要记录对应 redo log

开启事务后,InnoDB 层更新记录前,首先要记录相应的 undo log,如果是更新操作,需要把被更新的列的旧值记下来,也就是要生成一条 undo log,undo log 会写入 Buffer Pool 中的 Undo 页面。不过,在内存修改该 Undo 页面后,需要记录对应的 redo log。

redo log undo log 区别在哪?

这两种日志是属于 InnoDB 存储引擎的日志,它们的区别在于:

  • redo log 记录了此次事务「完成后」的数据状态,记录的是更新之后的值;
  • undo log 记录了此次事务「开始前」的数据状态,记录的是更新之前的值;

事务提交之前发生了崩溃,重启后会通过 undo log 回滚事务,事务提交之后发生了崩溃,重启后会通过 redo log 恢复事务,如下图:

所以有了 redo log,再通过 WAL 技术,InnoDB 就可以保证即使数据库发生异常重启,之前已提交的记录都不会丢失,这个能力称为 crash-safe(崩溃恢复)。可以看出来, redo log 保证了事务四大特性中的持久性。

redo log 文件写满了怎么办?

redo log 是循环写的方式,相当于一个环形,InnoDB 用 write pos 表示 redo log 当前记录写到的位置,用 checkpoint 表示当前要擦除的位置,如下图:

图中的:

  • write pos 和 checkpoint 的移动都是顺时针方向;
  • write pos ~ checkpoint 之间的部分(图中的红色部分),用来记录新的更新操作;
  • check point ~ write pos 之间的部分(图中蓝色部分):待落盘的脏数据页记录;

如果 write pos 追上了 checkpoint,就意味着 redo log 文件满了,这时 MySQL 不能再执行新的更新操作,也就是说 MySQL 会被阻塞(因此所以针对并发量大的系统,适当设置 redo log 的文件大小非常重要),此时会停下来将 Buffer Pool 中的脏页刷新到磁盘中,然后标记 redo log 哪些记录可以被擦除,接着对旧的 redo log 记录进行擦除,等擦除完旧记录腾出了空间,checkpoint 就会往后移动(图中顺时针),然后 MySQL 恢复正常运行,继续执行新的更新操作。

所以,一次 checkpoint 的过程就是脏页刷新到磁盘中变成干净页,然后标记 redo log 哪些记录可以被覆盖的过程。

### MySQL Redo Log 的工作原理及用途 #### 作用 MySQL 中的 Redo Log 是 InnoDB 存储引擎中的核心组件之一,主要用于保障数据库事务的一致性和持久性。当数据库发生崩溃时,Redo Log 能够帮助恢复未完成的数据写入操作,从而确保事务不会因为意外中断而丢失[^2]。 具体来说,Redo Log 记录了所有对数据页所做的修改操作。这些记录可以用来重新执行(即重做)那些已经提交但尚未完全写入磁盘的操作。通过这种方式,即使系统在某个时间点突然宕机,重启后也能利用 Redo Log 将数据恢复到最新的状态[^1]。 --- #### 结构 Redo Log 的存储结构由两部分组成:**Log Buffer** 和 **Log File**。 1. **Log Buffer**: 这是一个位于内存中的缓冲区,在服务器启动时会预先分配一片连续的空间作为 redo log buffer。所有的日志写入操作都会优先写入这个缓冲区中,而不是直接写入磁盘上的文件。这样做的目的是为了减少频繁的随机 IO 操作,提升性能[^4]。 2. **Log File**: 当 Log Buffer 达到一定条件(例如满了或者满足特定的时间间隔),其内容会被刷入磁盘上的物理文件中。这部分文件通常被称为 redo log file 或者 ib_logfile* 文件。它们保存着实际的日志数据,并且具有循环覆盖的特点——也就是说,旧的日志会在不再需要的时候被新日志替换掉。 此外,还存在一个重要的参数 `innodb_flush_log_at_trx_commit`,它可以控制何时将 Log Buffer 刷入磁盘: - 如果设置为 0,则每秒刷新一次; - 设置为 1 表示每次事务提交都立即同步到磁盘; - 设置为 2 同样也是按需写回缓存,不过仅保证一秒内至少有一次真正的 fsync() 操作。 --- #### 配置方法 以下是几个常用的配置项及其含义: 1. **innodb_log_file_size** - 定义单个 redo log 文件的最大尺寸,默认情况下可能不足以应对高负载环境下的需求。 - 修改此值需要注意停服重建表空间的过程可能会比较耗时。 2. **innodb_log_files_in_group** - 控制一组中有多少个 redo log files 可供轮转使用。 3. **innodb_log_buffer_size** - 如前所述,这是指定了 Log Buffer 大小的一个变量,默认值一般设得较小(如 16 MB)。对于大事务场景下建议适当调增以降低磁盘压力。 4. **sync_binlog** - Binlog 的同步频率虽然不直接影响 Redo Log,但如果两者配合不当也可能引发一致性问题,因此也需要关注它的取值范围。 --- ```sql -- 查看当前 redo log 参数配置 SHOW VARIABLES LIKE 'innodb%log%'; SET GLOBAL innodb_flush_log_at_trx_commit = 1; -- 动态调整trx commit行为 ``` 上述 SQL 查询语句可以帮助管理员快速获取关于 redo log 的现有设定情况并作出相应优化决策。 ---
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值