这是我参与更文挑战的第3天,活动详情查看:更文挑战
一、前言
在更新完 Buffer Pool 中的缓存页之后,必须要写一条 redo log,这样才能记录下对数据库做的修改。
redo log 可以保证事务提交之后,如果事务中的增删改查 SQL 语句更新的缓存页还没刷到磁盘上去,此时 MySQL 宕机了,那么 MySQL 重启之后,就可以把 redo log 重做一遍,恢复出来事务当时更新的缓存页,然后再把缓存页刷到磁盘。
redo log 本质是保证事务提交之后,修改的数据绝对不会丢失的。
redo log 写磁盘的过程,如图:
redo log 里本质上记录的是对某个表空间的某个数据页的某个偏移量的地方修改了几个字节的值,具体修改的值是什么。里面记录的是:
- 表空间号
- 数据页号
- 偏移量
- 修改几个字节的值
- 具体的值
根据修改了数据页里的几个字节的值,redo log 划分为不同的类型:
-
MLOG_1BYTE类型:修改了 1 个字节的值 -
MLOG_2BYTE类型:修改了 2 个字节的值 -
MLOG_WRITE_STRING类型:修改了一大串的值 -
等等
redo log 大致的结构如下:
日志类型(类是 MYLOG_1BYTE) 表空间ID 数据页号 数据页中的偏移量 具体修改的数据
二、redo log 详细
需要了解的概念:
-
redo log block:redo log块,类似数据页 -
redo log buffer:一连续内存,里面划分了N多个空的redo log block
redo log 是一条一条直接写入磁盘上的日志文件的嘛?
显然不是。
redo log不是单行单行的写入日志文件,而是用redo log block来存放多个单行日志。
MySQL 内另外一个数据结构:redo log block。
redo log block 共 512字节,组成:
header块头:12字节body块体:496字节trailer块尾:4字节
header 头又分为 4 个部分:
block no:4字节,块唯一编号data length:2字节,block里写入了多少字节数据first record group:2字节,每个事务都会有多个redo log,是一个redo log group,即一组redo log。存储第一组redo log的偏移量。checkpoint on:4字节
redo log 是如何写入日志文件里的 redo log block中?
先写入内存中
redo log buffer里的redo log block,等满 512字节,再一次性把这个redo log block写入磁盘文件。 当然也会有需求需要对某些字节进行修改,所以支持随机读写。
整体写入,如图:
redo log buffer 里的 redo log block 什么时候可以刷入磁盘文件里?
-
如果
redo log buffer的日志已经占据了redo log buffer总容量的一半了,也就是超过了8MB的redo log在缓存里了,此时就会把这些刷入磁盘文件里。 -
一个事务提交的时候,必须把他的那些
redo log所在的redo log block都刷入到磁盘文件里。
提交事务的时候,事务对应的
redo log必须是刷入磁盘文件,这才算是事务提交成功,否则事务提交失败。 只有这样,当事务提交之后,他修改的数据才不会丢失,因为redo log里有重做日志,随时可以恢复事务做的修改
-
后台线程定时刷新,有一个后台线程每隔 1秒 就会把
redo log buffer里的redo log block刷到磁盘文件里。 -
MySQL关闭的时候,redo log block都会刷入磁盘里。