MySQL的7种日志(二):RedoLog

0.前言

续上一篇: MySQL的7种日志(一):概况

上一篇我准备写MySQL日志还是2个月前的事,这两个月里生活发生了天翻地覆的变化,都没时间更新。

昨天跟朋友聊天立了flag说今天要续写一篇

于是中午吃饭时在纸上画了一个流程图。来介绍下MySQL里的RedoLog

1.几个问题

redolog和binlog一样记录的是数据修改后的记录。区别是什么,存在的意义是什么?

redolog和undolog的关系

relaylog的作用

2.修改数据的流程

下图是简化版的一个数据修改,真实的流程比这复杂很多,这里的数据修改不只是update,按页组织的insert/update/delete操作都是对页修改

数据修改流程

3.Redolog在数据库意外崩溃时的作用

当故障发生时,数据库意外当机,有部分内存中已修改的页(脏页)没来得及刷新到磁盘里。

在写入redo log时,会顺便记录XID,即当前事务id。在写入binlog时,也会写入XID。

如果在写入redo log之前崩溃,那么此时redo log与binlog中都没有,是一致的情况,崩溃也无所谓。

如果在写入redo log prepare阶段后立马崩溃,之后会在崩恢复时,由于redo log没有被标记为commit。于是拿着redo log中的XID去binlog中查找,此时肯定是找不到的,那么执行回滚操作。

如果在写入binlog后立马崩溃,在恢复时,由redo log中的XID可以找到对应的binlog,这个时候直接提交即可。

总的来说,在崩溃恢复后,只要redo log不是处于commit阶段,那么就拿着redo log中的XID去binlog中寻找,找得到就提交,否则就回滚。

在这样的机制下,两阶段提交能在崩溃恢复时,能够对提交中断的事务进行补偿,来确保redo log与binlog的数据一致性

数据修改流程在异常关机时的恢复

4.Redolog的刷盘

4.1 redlog的分组

一个事务中可能会包含多个page的修改,可能会产生多条redolog,所以redolog以组的方式写入 在一个事物中多次的数据修改,对应的就是多个数据页多个偏移量位置的字段变更,也就是说会产生多条redolog,一个组的redolog在持久化的时候,不能部分成功,部分失败,否则的话,就会破坏事务的原子性。

4.2 redolog的块

redolog是按照块组织在一起,然后写入到磁盘中的,类似于数据的页,而且引入了redo log buffer,默认的大小为16MB。buffer中分了很多的block,每个block的大小为512kb,每一个事务产生的所有redo log称为一个group。

4.3 redolog 刷盘时机

redo log 在从内存中持久化到redo log file的时候,也是有策略的,会有相应的配置,来设置持久化的时机

innodb_flush_log_at_trx_commit,这个参数,就是控制redo log 从内存中,写入到磁盘中的时机

4.4 redolog刷盘流程简介

RedoLo是循环写的。write pos可以看作是头,CheckPoint可以看作是尾。w->c是空闲的区域,c-w是已经写满的区域。写入时挪动w,落盘时挪动c,当w=c的位置时需要等待去落盘。 checkpoint就是负责落盘的,将数据存储到磁盘上并擦掉,由一个异步线程来执行的。

5.Redolog的配置

InnoDb引擎至少有一个日志文件从做组,每个文件组至少有2个重做日志文件,如默认的ib_logfile0和ib_logfile1。

innodb_log_file_size: 指定每个redo日志大小,默认值48MB
innodb_log_files_in_group: 指定日志文件组中redo日志文件数量,默认为2
innodb_log_group_home_dir: 指定日志文件组所在路劲,默认值./,指mysql的数据目录datadir
innodb_mirrored_log_groups: 指定日志镜像文件组的数量,默认为1,此功能属于未实现的功能,在5.6版本中废弃,在5.7版本中删除了。

show variables like ‘innodb%log%’; #列举RedoLog日志组的配置


总结.Redolog的作用

MySQL为了提升性能,每次对数据的更新,会先同步到BufferPool中,涉及到的数据页就会变成脏页。 同时会启动后台线程,异步地将脏页刷新到磁盘中。 如果在某个时间,MySQL突然崩溃,则内存中的BufferPool就会丢失,剩余未同步的数据就会直接消失。 虽然在更新BufferPool后,也写入了binlog中,但binlog并不具备crash-safe的能力。 因为崩溃可能发生在写binlog后,刷脏前。在主从同步的情况下,从节点会拿到多出来的一条binlog。 所以server层的binlog是不支持崩溃恢复的,只是支持误删数据恢复。InnoDB考虑到这一点,自己实现了redo log。

– done

>> Home

51ak

2022/05/13

Categories: mysql 日志 Tags: 原创 精品

《数据库工作笔记》公众号
扫描上面的二维码,关注我的《数据库工作笔记》公众号