mysql(四)redo log

本文介绍了InnoDB Redolog的作用,如何记录数据库修改,避免事务提交后数据丢失。详细讲解了Redolog的结构、刷盘策略和与binlog的区别。重点讨论了Redolog的写入时机、用途和应用场景,以及MySQL如何基于Redolog进行事务恢复。
摘要由CSDN通过智能技术生成

一、为什么引入redo log

先说redo log的用处:记录对数据库数据的修改,保证事务提交之后修改的数据不会丢失。用于事务前滚恢复的。

        我们都知道如果对mysql的值进行更新,此时如果存在一个事务,此时在buffer pool更新完值后提交事务。而我们都知道mysql对于buffer pool里面的缓存页的刷盘不是实时的,而是有另外的线程对这些缓存页进行定时的刷盘操作。那么如果此时事务提交成功后这些缓存页还没进行刷盘操作就断电了,这时会导致这些数据都丢失了。

可我们明明事务提交成功了啊,这就会导致事务提交成功后数据丢失问题。

所以mysql则引入了一个用来记录修改的日志redo log。

在innodb中会有一个redo log buffer,会进行相应的redo log的记录,然后根据刷盘策略将内存中的数据写入到磁盘的日志文件。

这种日志的大概格式是:对xx表空间中的xxx数据页中的偏移量为xxx的地方更新了xxx数据。

 

二、redo log的大概结构

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

根据你修改了数据页里的几个字节的值,redo log会被划分为不同的类型。

1)、MLOG_1BYTE:修改了1个字节的值

2)、MLOG_2BYTE:修改了2个字节的值。4、8字节等依次类推

3)、MLOG_WRITE_STRING:修改了大量的值。

所以一条redo log看起来大致结构如下:


日志类型(就是类似MLOG_1BYTE之类的),表空间ID,数据页号,数据页中的偏移量,具体修改的数据

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

日志类型(就是类似MLOG_1BYTE之类的),表空间ID,数据页号,数据页中的偏移量,修改数据长度,具体修改的数据

三、redo log是一条一条写入日志文件的?

redo log进行刷盘时,并不是一条一条的写入日志文件的。

mysql中有一个数据结构,叫做redo log block——————用来存放多个单行日志的。

一个redo log block是512字节,该redo log block分为3个部分:12字节的header头、496字节的body块、4字节的trailer尾

而12个字节的header又分为4个部分:
1、4个字节的block no ————块的唯一编号。

2、2字节的data length ————block里写入了多少个字节数据。

3、2个字节的first record group ————每个事务会有多个redo log ,则几个redo log是一个redo log group(即一组redo log),那么这个block里的第一组redo log的偏移量就是存储在这两个字节中。

4、4个字节的checkpoint on

所以,事实上mysql每次的redo log是先往redo log block中加入的(一个block可以存放496个自己的redo log),然后再将redo log block写入磁盘中。如下图:

上面这些操作都是基于redo log buffer,redo log buffer类似于buffer pool,是再mysql启动时申请的连续内存空间。

可以通过设置mysql的inodb_log_buffer_size来指定这个redo log buffer的大小,默认大小是16M。

四、redo log的刷盘策略

对于redo log(redo log block)的刷盘策略主要有四条:

1、如果写入的redo log buffer日志占据本身大小的一半,此时就会将他们刷入磁盘

2、一个事务提交时,必须把那些所在的redo log所在的redo log block刷入磁盘文件中去(默认情况下innodb_flush_log_at_trx_commit为1,可修改其值自定义事务提交时的刷盘操作)

该情况又分为三种:

mysql每执行新一条dml语句都会先将日志记录在redo log buffer,后续在某个时间点再将多条操作记录写到redo log file,这种先写日志再写磁盘的技术就是mysql中WAL技术(writing-ahead logging)。
在计算机的操作系统中用户空间缓冲区的数据是无法直接写入磁盘的,中间必需经过操作系统缓冲区(OS Buffer)。因此,redo log buffer写入redo log file,实际上会先写入OS Buffer,然后再调用fsync()将其刷入到redo log file。

redo log刷盘步骤:redo log buffer→os buffer→磁盘(redo log file)

铺垫了这么多,redo log在什么时候写入磁盘呢?

mysql通过innodb_flush_log_at_trx_commit配置来控制redo log的写盘时机。

0:延迟写。提交事务时不会将redo log写入os buffer,而是每隔1秒将redo log写入os buffer并调用fsync()刷入磁盘。系统崩溃会丢失一秒钟的数据。
1:实时写,实时刷。每次提交事务都将redo log写入os buffer并调用fsync()刷入磁盘。这种方式系统奔溃不会丢失数据,因每次提交事务都写入磁盘,性能比较差(推荐)
2:实时写,延时刷。每次提交事务都将redo log写入os buffer,但并不会马上调用fsync()刷如磁盘,而是间隔1秒调fsync()刷盘。相对于每次提交都写盘和每隔1秒写盘,实施写os buffer延时刷盘是一个数据一致性与性能的之间的这种方案。

一般都是推荐设置为1,因为redo log的本身就是为了保证事务提交后数据不丢失的。而且其实redo log的写磁盘操作时顺序写入的,性能也是比较高的。

3、后台线程定时刷新,有一个后台线程每隔1s就会把redo log buffer 里的redo log block刷盘

4、mysql关闭时,redo log block都会进行刷盘。

总结一句:redo log是用来解决事务提交数据丢失的,所以刷盘时机一般最常见的是第二种情况

五、redo log日志文件

为了避免大量的数据只写入一个文件,导致文件太大。

实际情况下,redo log都会写入到一个目录中的文件里,这个目录可以通过 show variables like ‘datadir’  ,也可以通过innodb_log_group_home_dir参数来设置这个目录。

这样redo log文件就可以有多个了,写满一个写下一个。一个默认时48MB,默认两个。可以通过innodb_log_file_size指定文件大小;用innodb_log_files_in_group来指定文件个数。

默认情况下目录就只有连两个文件:ib_logfile0和ib_logfile1,每个48MB。写满第一个就写第二个,第二个写满了就覆盖第一个的内容。

 

六、提出问题

redo log 和 binlog的区别?写入时机?作用?应用场景?mysql怎么基于redo log来恢复事务数据?binlog怎么恢复数据同步数据的?

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值