18.redo log 的格式

93 阅读8分钟

redo log的格式

redo log里本质上记录的就是在对某个表空间的某个数据页的某个偏移量的地方修改了几个字节的值,具体修改的值是什么,他里面需要记录的就是表空间号+数据页号+偏移量+修改几个字节的值+具体的值

所以根据你修改了数据页里的几个字节的值,redo log就划分为了不同的类型:

MLOG_1BYTE类型的日志指的就是修改了1个字节的值

MLOG_2BYTE类型的日志指的就是修改了2个字节的值,

以此类推,还有修改了4个字节的值的日志类型,修改了8个字节的值的日志类型。

当然,如果你要是一下子修改了一大串的值,类型就是MLOG_WRITE_STRING,就是代表你一下子在那个数据页的某个偏移量的位置插入或者修改了一大串的值。

所以其实一条redo log看起来大致的结构如下所示: image.png

一条redo log里面记录的就是这些东西,那么一条redo log表达的语义就很明确了。

日志类型:,,数据页号,,

表空间ID:在哪个表空间里操作的,这个就是跟你SQL在哪个表里执行的是对应的。

接着就是在这个表空间的哪个数据页里执行的

数据页中的偏移量:在数据页的哪个偏移量开始执行的

具体修改的数据:具体更新的数据是哪些呢。

日志类型:比如MLOG_1BYTE,通过它的类型就可以知道这次增删改操作修改了多少字节的数据。

表空间 ID:在哪个表空间操作的,这个表空间和逻辑概念中的数据表是对应的,此外对于 InnoDB 引擎而言,表空间你可以理解为磁盘上的一个 .ibd 文件,比如我们用 SQL 操作数据表 student ,那么底层就会操作磁盘文件 student.ibd。

数据页号:修改了表空间中的哪些数据页。

数据页中的偏移量:从数据页的哪个位置开始修改的。

具体修改的数据:无需解释了,就是修改之后的数据。

有了上述信息,就可以精准完美的还原出来一次数据增删改操作做的变动了。

但如果是MLOG_WRITE_STRING类型的日志,因为不知道具体修改了多少字节的数据,所以其实会多一个修改数据长度,就告诉你他这次修改了多少字节的数据,如下所示他的格式:

日志类型,表空间ID,数据页号,数据页中的偏移量,修改数据长度,具体修改的数据。

image.png 所以这就是 redo log 的底层结构,至少从表面上看并不复杂。当然如果往深了说还是很复杂的,比如 redo log 还会记录你更新了哪些索引之类的,这些留到后面再说。目前只需要对 redo log 有一个大致的了解即可,当 Buffer Pool 更新完数据之后,就会以上面这种格式往 redo log 日志文件里面写入一条 redo log 日志,来记录本次的修改。

参考:www.360doc.com/content/22/…

redo log block

redo log是一条一条的直接就往磁盘文件里写入吗?

可能有一些朋友会认为就是如此简单粗暴的往磁盘文件里写,但其实并没那么简单!

接下来几天我们就会揭秘一下这个redo log写磁盘的过程。

首先大家看下面的图,学习到现在,我想任何一个朋友一看下面的图就知道是怎么回事了

平时我们执行CRUD的时候,从磁盘加载数据页到buffer pool的缓存页里去,然后对缓存页执行增删改,同时还会写redo log到日志文件里去,后续不定时把缓存页刷回磁盘文件里去,大概就是这个原理,如下图所示:

image.png

那么上次我们也介绍了一下每一条redo log长什么样子,说白了,他就是记录了:

表空间号+数据页号+数据页内偏移量+修改了几个字节的数据+实际修改数据

就是简简单单这么一条日志罢了

所以大家可以想一下,redo log就是按照上述格式,一条一条的直接就写入到磁盘上的日志文件里去了吗?

显然不是的!

其实MySQL内有另外一个数据结构,叫做redo log block,大概你可以理解为,平时我们的数据不是存放在数据页了的么,用一页一页的数据页来存放数据。

那么对于redo log也不是单行单行的写入日志文件的,是用redo log block来存放多个单行redo log日志的。

一个redo log block是512字节,这个redo log block的512字节分为3个部分。

一部分是12字节的header块头。

一部分是496字节的body块体。

一部分是4字节的trailer块尾。

如下图所示

image.png

在这里面,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。

我们看下图,这个header可以进行进一步的区分。

image.png

所以我们看到上图就知道,其实对于我们的redo log而言,他确实是不停的追加写入到redo log磁盘文件里去的,但是其实每一个redo log都是写入到文件里的一个redo log block里去的,一个block最多放496自己的redo log日志。

此时可能有人会有疑问了,到底一个一个的redo log block在日志文件里是怎么存在的?那么一条一条的redo log又是如何写入日志文件里的redo log block里去的呢?估计很多人都很奇怪这个问题。

所以我们接下来就给大家解答这个问题。

大家先想一下,假设你有一个redo log日志文件,平时我们往里面写数据,你大致可以认为是从第一行开始,从左往右写,可能会有很多行,比如下面那样子,你看看是不是你理解的那样?

image.png

好,那么所以现在既然如此,假设你要写第一个redo log了,是不是应该起码是先在内存里把这个redo log给弄到一个redo log block数据结构里去?

然后似乎你应该是等内存里的一个redo log block的512字节都满了,再一次性把这个redo log block写入磁盘文件?

如下图所示

image.png 然后其实按照我们所说的,一个redo log block就是512字节,那么是不是真正写入的时候,把这个redo log block的512字节的数据,就写入到redo log文件里去就可以了?那么redo log文件里就多了一个block,如下图所示。

image.png

所以大家看到上图演示之后,对于这个所谓的redo log和redo log block的关系,以及redo log block如何进入日志文件,日志文件里是如何存放一个又一个的redo log block的,应该都很清楚了!

其实有一定开发经验的朋友都知道,写文件的时候,可以按照字节,一个字节一个字节的写入的,文件里存放的东西就是很多很多字节,依次排开,然后其中可能512个字节组合起来,就固定代表了一个redo log block。

这其实就是任何一个中间件系统,数据库系统,底层依赖磁盘文件存储数据的一个共同的原理,所以大家也不用把这个复杂数据写入磁盘文件想象的太复杂了。

那么如果依次在磁盘文件里的末尾追加不停的写字节数据,就是磁盘顺序写;但是假设现在磁盘文件里已经有很多很多的redo log block了,此时要在磁盘里某个随机位置找到一个redo log block去修改他里面几个字节的数据,这就是磁盘随机写,看下图。

image.png

redo log block的数据结构和他与磁盘文件的关系都已经的很清楚了,明天我们继续了解redo log buffer,就是redo log是如何通过一个内存缓冲数据结构之后,再进入到磁盘文件的!

image.png

参考:blog.csdn.net/zht24564812…