1:Redo Log的重要性
MySql作为互联网行业使用最多的关系型数据库之一,其InnoDB存储引擎本身就支持事务,MySql的事务实现离不开Redo Log和Undo Log,从某种程度来说,事务的隔离性由锁和MVCC机制实现,原子性和持久性由Redo Log实现,一致性由Undo Log实现。所以我们有必要深入了解一下Undo Log的原理
2:Redo Log的基本概念
Redo Log也被称为重做日志,它是在InnoDB存储引擎中产生的,用来保证事务的原子性和持久性。Redo Log主要记录的是物理日志,也就是对磁盘上的数据进行修改操作。Redo Log往往用来恢复提交后的物理数据页。不过只能恢复到最后一次提交的位置
Redo Log通常包含俩部分:
- 1:内存中的日志缓冲,称作Redo Log Buffer,这部分日志再内存中,容易丢失
- 2:存放在磁盘上的重做日志文件,称做Redo Log File,这部分日志是持久化到磁盘上的,不容易丢 失,除非磁盘坏了
3:Redo Log基本原理
Redo Log能够保证事务的原子性和持久性,在MySql发生故障时,尽力避免内存中的脏页数据写入数据表的IBD文件。在重启MySql服务时,可以根据Redo Log恢复事务已经提交但是还没有写入IBD文件中的数据,从而对事务提交的数据进行持久化操作
4:Redo Log刷盘流程
在MySql的InnoDB存储引擎中,通过提交事务强制执行写日志操作机制实现事务的持久化。InnoDB存储引擎为了保证在事务提交时,将日志保存到事务日志文件中,默认每次将Redo Log Buffer中的日志写入日志文件时,都调用操作系统的fsync()函数,因为MySql进程和其占用的内存空间都工作在操作系统的用户空间中,所以MySql的Log Buffer也工作在操作系统的用户工作中。默认情况下,如果想要将Log Buffer中的数据持久化到磁盘的日志文件中,还需要经过操作系统的内核空间缓冲区。也就是OS Buffer。大致流程如下
5:Redo Log刷盘机制
-
5.1:开启事务,发出提交事务的指令后是否刷新日志由变量innodb_flush_log_at_trx_commit决定
-
5.2:每秒刷新一次,刷新日志的频率由变量innodb_flush_log_at_timeout的值决定,默认是1s,需要注意的是,刷新日志的频率和是否执行了commit操作无关
-
5.3:当Log Buffer中已经使用的内存超出一半时,也会触发刷盘机制
-
5.4:当事务中存在checkpoint时,在一定程度上代表了刷写到磁盘时日志所处的LSN位置,其中LSN表示日志的逻辑序列号
6:5.1开启事务
当事务提交时,需要先将事务日志写入到Log Buffer中,这些写入到Log Buffer的日志并不是随着事务的提交立刻写入磁盘的,而是根据一定的规则将Log Buffer中的日志写入到磁盘文件中的。从而保证了Redo Log文件数据的持久性。这种刷盘规则可以通过innodb_flush_log_at_trx_commit变量控制,有可选值0,1,2三种。默认为1,每个值代表的刷盘规则如下
| 参数值 | 简介 |
|---|---|
| 0 | 每次提交事务时,不会将Log Buffer的日志写入到OS Buffer中。而是通过一个单独的线程,每过1秒将Log Buffer的日志数据写入OS Buffer并调用fsync()函数写入磁盘的Redo Log文件。这种方式不是实时写磁盘的,而是每隔1s写一次日志,如果MySql奔溃,又可能会丢失这1s的数据 |
| 1 | 每次提交事务都会将Log Buffer中的日志写入OS BNuffer中。并且会调用fsync()函数将日志写入到磁盘,这种方式不会丢失数据,但是性能较差,默认是1 |
| 2 | 每次提交事务时,都只是将数据写入OS Buffer,之后每隔1s,通过fsync()将日志数据写入到磁盘,也是会丢失数据的 |
7:Redo Log写入机制
Redo Log主要记录的是物理日志,文件内容是以顺序循环的方式写入的,一个文件写满了就会写下一个文件,最后一个文件写满了就会从第一个文件的开始覆盖写入。其中有几个参数
| 参数 | 作用 |
|---|---|
| Write Pos | 是数据表中当前记录所在的位置,随着不断地向数据表中写数据,这个位置会向后移动,当移动到最后一个文件的最后一个位置时,又回回到第一个文件的开始位置进行写操作 |
| CheckPoint | 是当前需要擦除的位置,这个位置也是向后移动的。移动到最后一个文件的最后一个位置时候,也会回到第一个文件的第一个位置进行擦出,只不过在擦除记录之前需要先讲数据持久化到磁盘 |
Write Pos和CheckPoint存在间隔,如果间隔很小甚至没有间隔,则表示数据已经写满,需要先擦除数据,此时不能再向Redo Log文件中写数据了