42 redo log是直接一条一条写入文件的吗?非也,揭秘redo log block!
揭秘redo log写磁盘的过程
平时我们执行CRUD的时候,从磁盘加载数据页到buffer pool的缓存页里去,然后对缓存页执行增删改,同时还会写redo log到日志文件里去,后续不定时把缓存页刷回磁盘文件里去,大概就是这个原理,如下图所示:
每一条redo log长什么样子
说白了,他就是记录了:
表空间号+数据页号+数据页内偏移量+修改了几个字节的数据+实际修改数据
就是简简单单这么一条日志罢了。
redo log不是一条一条的直接就写入到磁盘上的日志文件里去。其实MySQL内有另外一个数据结构,叫做redo log block。
大概你可以理解为,平时我们的数据不是存放在数据页了的么,用一页一页的数据页来存放数据。那么对于redo log也不是单行单行的写入日志文件的,他是用一个redo log block来存放多个单行日志的。
redo log block组成
一个redo log block是512字节,这个redo log block的512字节分为3个部分,一个是12字节的header块头,一个是496字节的body块体,一个是4字节的trailer块尾。
如下图所示
在这里面,12字节的header头又分为了4个部分。
- 包括4个字节的
block no
,就是块唯一编号; - 2个字节的
data length
,就是block里写入了多少字节数据; - 2个字节的
first record group
。这个是说每个事务都会有多个redo log,是一个redo log group
,即一组redo log。那么在这个block里的第一组redo log的偏移量,就是这2个字节存储的; - 4个字节的
checkpoint on
如图所示

所以我们看到上图就知道,其实对于我们的redo log而言,他确实是不停的追加写入到redo log磁盘文件里去的,但是其实每一个redo log都是写入到文件里的一个redo log block里去的,一个block最多放496自己的redo log日志。
到底一个一个的redo log block在日志文件里是怎么存在的?那么一条一条的redo log又是如何写入日志文件里的redo log block里去的呢?
假设你有一个redo log日志文件,平时我们往里面写数据,你大致可以认为是从第一行开始,从左往右写,可能会有很多行,比如下面那样子,

好,那么所以现在既然如此,假设你要写第一个redo log了,是不是应该起码是先在内存里把这个redo log给弄到一个redo log block数据结构里去?
然后似乎你应该是等内存里的一个redo log block的512字节都满了,再一次性把这个redo log block写入磁盘文件?
如下图所示

然后其实按照我们所说的,一个redo log block就是512字节,那么是不是真正写入的时候,把这个redo log block的512字节的数据,就写入到redo log日志文件里去就可以了?那么redo log文件里就多了一个block,如下图所示。
所以大家看到上图演示之后,对于这个所谓的redo log和redo log block的关系,以及redo log block如何进入日志文件,日志文件里是如何存放一个又一个的redo log block的,应该都很清楚了!
写文件的时候,可以按照字节,一个字节一个字节的写入的,文件里存放的东西就是很多很多字节,依次排开,然后其中可能512个字节组合起来,就固定代表了一个redo log block。
这其实就是任何一个中间件系统,数据库系统,底层依赖磁盘文件存储数据的一个共同的原理。
那么如果依次在磁盘文件里的末尾追加不停的写字节数据,就是磁盘顺序写;但是假设现在磁盘文件里已经有很多很多的redo log block了,此时要在磁盘里某个随机位置找到一个redo log block去修改他里面几个字节的数据,这就是磁盘随机写,看下图。
疑问?
block写满512才刷盘,那没满512的时候mysql挂了咋办?
假设现在磁盘文件里已经有很多的redo log block了,此时要在磁盘里某个随机位置找到一个redo log block 去修改里面的几个字节的数据,这种场景什么时候会发生呢?