首先要明确,某个行为修改了某个数据页(Page => Page’),产生了Redo日志。那么:

  • 应用Redo日志可以重新产生数据页Page’

我们称,Redo日志记录等价于已修改的数据页(脏页)

在InnoDB中,Redo日志的生命周期是:

  1. 在MTR中产生Redo日志和脏页
  2. 每个MTR都将各自的Redo日志提交到公共Log Buffer(默认8MB)中,Log Buffer中保存的日志就是完整的Redo日志格式(包含Header和Tailer)
  3. 公共Log Buffer将Redo日志刷写到磁盘上
  4. 脏页异步的(时间不确定的)写到磁盘上

这里有如下三个限制

  • 【1】公共Log Buffer是循环使用
  • 【2】磁盘上的Redo日志(ib_logfile)是循环使用
  • 【3】脏页写入磁盘之前,保证这个与脏页等价的Redo日志已经写入磁盘

那么我们看如何保证这三个限制

限制1

将公共Log Buffer分为若干个区域:

定义了四个LSN,将Log Buffer分成五个区间。
其实是可以根据一条日志的LSN计算出该条日志在Redo日志文件中的偏移,我们说LSN和日志偏移是一一对应的,这四个LSN等价的四个偏移将Log Buffer分成五个区间

区域 说明
区域 说明
无 —
flushed_to_disk_lsn
之前的日志已经写入磁盘
flushed_to_disk_lsn

written_to_all_lsn
日志已经写入文件(操作系统缓冲区),但是未刷写到磁盘
written_to_all_lsn

write_lsn
这个区间的日志正在写入文件(操作系统缓冲区),但还未确保全部已写入到文件(操作系统缓冲区)
write_lsn

buf_free
这个区间的日志只存在于Log Buffer中,还未开始写入文件(操作系统缓冲区)
buf_free — 空闲的Log Buffer的起始位置

限制2

InnoDB默认有两个Redo日志文件:log_file0 / log_file1,当log_file1写满后,会从log_file0的起始位置写入(循环写)
如果一条Redo日志记录对应的脏页还没有刷写到磁盘,需要防止这条Redo日志被“覆盖写”,这里由Checkpoint机制保证
参考InnoDB(二):Checkpoint,InnoDB的Checkpoint主要工作为:

  • 【1】产生一个Checkpoint_LSN
  • 【2】保证所有LSN<Checkpoint_LSN的Redo日志对应的脏页已持久化(刷写入磁盘,这些Redo日志可以被删除或“覆盖写”)

容易理解,最近Checkpoint之前的Redo日志都是可以被“安全覆盖”的
log_checkpoint_margin

限制3

在将脏页刷写入磁盘前,会先保证等价的Redo日志已刷写入磁盘