更新完Buffer Pool中的缓存页之后,必须要写一条redo log,记录下对数据库做的修改
redo log 可以保证事务提交之后,事务中的增删查改SQL语句更新的缓存页还没刷到磁盘上去,MySQL 宕机了,重启过后,redo log 重做一遍,就能恢复出来事务当时更新的缓存页,在把缓存页刷到磁盘即可。

redo log本质是保证事务提交之后,修改的数据绝对不会丢失的。
image.png

image.png
你更新缓存页的时候,会更新free链表、flush链表、lru链 表,然后有专门的后台IO线程,不定时的根据flush链表、lru链表,会把你更新过的缓存页刷新回磁盘文件的数据页里 去

image.png
所以大家都知道这个机制里最大的漏洞就在于,万一你一个事务里有增删改SQL更新了缓存页,然后事务提交了,结果万一你还没来得 及让IO线程把缓存页刷新到磁盘文件里,此时MySQL宕机了,然后内存数据丢失,你事务更新的数据就丢失了!
但是也不可能每次你事务一提交,就把你事务更新的缓存页都刷新回磁盘文件里去,因为大家之前也都知道,缓存页 刷新到磁盘文件里,是随机磁盘读写,性能是相当的差!这会导致你数据库性能和并发能力都很弱的
引入一个redo log机制,这个机制就是说,你提交事务的时候,绝对是保证把你对缓存页做的修改以日 志的形式,写入到redo log日志文件里去的 。

image.png
事务提交的时候把修改过的缓存页都刷入磁盘,跟你事务提交的时候把你做的修改的redo log都 写入日志文件,他们不都是写磁盘么?差别在哪里? 把修改过的缓存页都刷入磁盘,这首先缓存页一个就是16kb,数据比较大,刷入磁盘比较耗时,而且 你可能就修改了缓存页里的几个字节的数据,难道也把完整的缓存页刷入磁盘吗? 你缓存页刷入磁盘是随机写磁盘,性能是很差的,因为他一个缓存页对应的位置可能在磁盘文件的一个随机位 置 。
但是如果是写redo log,第一个一行redo log可能就占据几十个字节,就包含表空间好、数据页号、磁盘文件偏移 量、更新值,这个写入磁盘速度很快。 此外,redo log写日志,是顺序写入磁盘文件,每次都是追加到磁盘文件末尾去,速度也是很快的。
提交事务的时候,用redo log的形式记录下来你做的修改,性能会远远超过刷缓存页的方式,这也可以让你的 数据库的并发能力更强。

需要记录的就是表空间号+数据页号+偏移量+修改几个字节的值+具体 的值
格式如下:对表空间XX中的数据页XX中的偏移量为XXXX的地方更新了数据XXX
根据你修改了数据页里的几个字节的值,redo log就划分为了不同的类型 , MLOG_1BYTE类型的日志指的就是修 改了1个字节的值,MLOG_2BYTE类型的日志指的就是修改了2个字节的值 , MLOG_WRITE_STRING 代表你一下子在那个数据页的某 个偏移量的位置插入或者修改了一大串的值
日志类型(就是类似MLOG_1BYTE之类的),表空间ID,数据页号,数据页中的偏移量,具体修改的数据

是MLOG_WRITE_STRING类型的日志,因为不知道具体修改了多少字节的数据,所以其实会多一个修改数 据长度,就告诉你他这次修改了多少字节的数据,如下所示他的格式
日志类型(就是类似MLOG_1BYTE之类的),表空间ID,数据页号,数据页中的偏移量,修改数据长度,具体修改的数据

redo log 是一条一条写入文件的吗?

MySQL 内有一个数据结构,叫redo log block ,来存放多个单行日志,
一个redo log block是512字节,这个redo log block的512字节分为3个部分,一个是12字节的header块头,一个是 496字节的body块体,一个是4字节的trailer块尾

image.png
image.png

其实对于我们的redo log而言,他确实是不停的追加写入到redo log磁盘文件里去的,但 是其实每一个redo log都是写入到文件里的一个redo log block里去的(内存中),一个block最多放496个字节自己的redo log日志

image.png