一、redo log日志基本结构
之前说到redo log 是重做日志,里面的记录的日志偏向物理日志,那么日志的内容大家有想过吗?其实redo log日志里面记录的主要是:表空间+数据页号+偏移量+修改几个字节的值+具体的值。根据你修改了数据页里的几个字节的值,redo log就划分为了不同的类型,MLOG_1BYTE类型的日志指的就是修改了1个字节的值,MLOG_2BYTE类型的日志指的就是修改了2个字节的值,以此类推,还有修改了4个字节的值的日志类型,修改了8个字节的日志类型。如果修改了一大串的值,类型就是:MLOG_WRITE_STRING,就是代表你一下子在哪个数据页的某个偏移量的位置插入或者修改了一大串的值。所以redo log看起来的结构如下:
日志类型(类似MLOG_1BYTE之类的数据),表空间ID,数据页号,数据页中的偏移量,修改数据长度(MLOG_WRITE_STRING类型的才有),具体修改的数据
Redo Log的刷盘策略:设置参数:innodb_flush_log_at_trx_commit
0:每秒一次,把log buffer写入os buffer,并调用fsync刷到磁盘
1:每次提交事务时,把log buffer写入os buffer,并调用fsync刷到磁盘
2:每次提交事务时,只是写入到os buffer,然后每秒一次调用fsync将日志刷新到磁盘
二、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
![](https://i-blog.csdnimg.cn/blog_migrate/064872b017a87d473325ce8032669c40.png)
不停的追加写入到redo log磁盘文件里去(注意:这里是顺序写),其实每一个redo log都是写入到文件里的一个redo log block里去的,一个block最多放569字节的redo log日志。
![](https://i-blog.csdnimg.cn/blog_migrate/2a622b21397059bb4577607634eee406.png)
三、redo log buffer
之前讲过:redo log数据会先写入redo log buffer中,之后再由后台线程根据配置的刷盘策略,将redo log buffer中的数据刷入磁盘中。这个redo log buffer其实就是mysql在启动的时候,申请的一块连续的内存空间,大概可以认为相当于buffer pool。buffer pool是申请之后划分了N个空的缓存页和一些链表结构。redo log buffer也是类似的,他是申请出来的一篇连续内存,然后里面划分出了N多个空的redo log block,如下图:
![](https://i-blog.csdnimg.cn/blog_migrate/754e37b9a127d56fd7bbe1055f65f398.png)
写满一个redo log block,就会继续写下一个redo log block,以此类推,直接到所有的redo log block都写。如果redo log buffer里所有的redo log block都写满了,那么此时必然会强制把redo log block刷盘。
平时执行一个事物的过程中,每个事务会有多个CRUD操作,那么就会有多个redo log,这么多个redo log就是一组redo log,其实每次一组redo log都是先在别的地方暂存,然后都执行完了,再把一组redo log给写入到redo log buffer的block里去的。如果一组redo log实在太多就有可能会存放在俩个redo log block中。
![](https://i-blog.csdnimg.cn/blog_migrate/07ee6afc1d5e8aaac2ed0a977427ffc2.png)
如果一个redo log group比较小,那么可能多个redo log group是在一个redo log block中。
![](https://i-blog.csdnimg.cn/blog_migrate/15aef1e08409e818c092e5caa6f66975.png)
四、redo log block刷盘时机
redo log block刷盘的时机:
如果写入redo log buffer的日志已经占据了redo log buffer总容量的一半了,也就是超过了8MB的redo log在缓冲里了,此时就会把他们刷入到磁盘文件里去。
一个事物提交的时候,必须把他那些redo log所在的redo log block都刷入到磁盘文件里去,只有这样,当事务提交之后,他修改的数据绝对不会丢失,因为redo log里有重做日志,随时可以回复事务做的修改。(这个和刷盘策略配置有关)
后台线程定时刷新,有一个后台线程每隔1秒就会把redo log buffer里的redo log block刷到磁盘文件里去。
mysql关闭的时候,redo log block都会刷入到磁盘里去。
五、redo log日志文件的了解
平时生产环境一定会产生大量的redo log写入日志文件,那么这个日志文件是不是有大小限制呢,个数限制呢?我们可以通过:
show variables like 'datadir' :查看日志文件目录
innodb_log_group_home_dir:设置文件目录
innodb_log_file_size:设置文件大小,默认是48MB
innodb_log_files_in_group:指定日志文件的数量,默认是2
所以默认情况下,目录就俩个日志文件,分别为:ib_logfile0和ib_logfile1,每个文件48MB,如果第一个日志文件写满了,我们接着写第二个日志文件,要是第二个日志文件写满了怎么办呢?会继续写第一个日志,覆盖第一个日志文件原来的redo log就可以了。
借道友法力一用:
![](https://i-blog.csdnimg.cn/blog_migrate/628ef03d790e160e7bdeb16f20d97c27.png)
========================== stay hungry stay foolish =============================