【MySQL】redo-log 保证事务提交

685 阅读3分钟

这是我参与更文挑战的第3天,活动详情查看:更文挑战

一、前言

在更新完 Buffer Pool 中的缓存页之后,必须要写一条 redo log,这样才能记录下对数据库做的修改。

redo log 可以保证事务提交之后,如果事务中的增删改查 SQL 语句更新的缓存页还没刷到磁盘上去,此时 MySQL 宕机了,那么 MySQL 重启之后,就可以把 redo log 重做一遍,恢复出来事务当时更新的缓存页,然后再把缓存页刷到磁盘。

redo log 本质是保证事务提交之后,修改的数据绝对不会丢失的。

redo log 写磁盘的过程,如图:

redo-log1.png

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

  • 表空间号
  • 数据页号
  • 偏移量
  • 修改几个字节的值
  • 具体的值

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

  • MLOG_1BYTE 类型:修改了 1 个字节的值

  • MLOG_2BYTE 类型:修改了 2 个字节的值

  • MLOG_WRITE_STRING 类型:修改了一大串的值

  • 等等

redo log 大致的结构如下:

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



二、redo log 详细

需要了解的概念:

  1. redo log blockredo log 块,类似数据页

  2. redo log buffer:一连续内存,里面划分了 N 多个空的 redo log block

redo log 是一条一条直接写入磁盘上的日志文件的嘛?

显然不是。 redo log 不是单行单行的写入日志文件,而是用 redo log block 来存放多个单行日志。

MySQL 内另外一个数据结构:redo log block

redo log block512字节,组成:

redolog1.png

  • header 块头:12字节
  • body 块体:496字节
  • trailer 块尾:4字节

header 头又分为 4 个部分:

  • block no4字节,块唯一编号
  • data length2字节block 里写入了多少字节数据
  • first record group2字节,每个事务都会有多个 redo log,是一个 redo log group,即一组 redo log。存储第一组 redo log 的偏移量。
  • checkpoint on4字节

redo log 是如何写入日志文件里的 redo log block中?

先写入内存中 redo log buffer 里的 redo log block,等满 512字节,再一次性把这个 redo log block 写入磁盘文件。 当然也会有需求需要对某些字节进行修改,所以支持随机读写。

整体写入,如图:

redolog2.png

redo log buffer 里的 redo log block 什么时候可以刷入磁盘文件里?

  1. 如果 redo log buffer 的日志已经占据了 redo log buffer 总容量的一半了,也就是超过了 8MBredo log 在缓存里了,此时就会把这些刷入磁盘文件里。

  2. 一个事务提交的时候,必须把他的那些 redo log 所在的 redo log block 都刷入到磁盘文件里。

提交事务的时候,事务对应的 redo log 必须是刷入磁盘文件,这才算是事务提交成功,否则事务提交失败。 只有这样,当事务提交之后,他修改的数据才不会丢失,因为 redo log 里有重做日志,随时可以恢复事务做的修改

  1. 后台线程定时刷新,有一个后台线程每隔 1秒 就会把 redo log buffer 里的 redo log block 刷到磁盘文件里。

  2. MySQL 关闭的时候, redo log block 都会刷入磁盘里。