数据库
首页 > 数据库> > MySQL学习(十)redo log 介绍

MySQL学习(十)redo log 介绍

作者:互联网

前言

我们将从缓冲池开始介绍 ,然后后面开始介绍了 redo log 的底层到底是如何记录物理日志的.

缓冲池

在介绍 redo log 之前我们将会先介绍缓冲池 ,方便后续知道 redo log 的动机 .
InnoDB存储引擎是基于磁盘存储的 ,并将其中的记录按照页的方式进行管理 ,这一点有点像超级系统的 page cache ,我们之前也发过这张图片 ,是一个 SQL 语句的执行过程 ,其中可以看到是否命中内存就是命中数据库的记录是否在 page 中 .

图例

那么我们可以想一下 ,假如我们需要读取更改某个页, 就想操作系统一样 ,操作系统当发生缺页的时候 ,操作系统就需要等待数据加载到 page 之后才能进行操作 ,所以 MySQL 采用 WAL (Write Ahead Log) 的方式来加快写 ,先将SQL 操作写入到 redo log ,再修改 page , 也就是说redo log 和 page 里面的数据是最新的数据 ,而磁盘里的数据是最旧 ,那么什么时候把脏数据刷新到磁盘中去呢? MySQL 回刷的时间点称之为 : Checkpoint

1297993-20211007214710930-2009572723.png

到了 checkpoint 就会将脏页回刷到磁盘 ,回刷的时机 :

(1) InnoDB 的 redo log 写满了,即是 write position 的位置追到了 checkpoint 的位置,这时候系统就会停止所有更新操作,把 checkpoint 往前推进,redo log 留出空间继续写。
(2) 系统内存不足,因为 MySQL 的数据都缓存在内存中,当系统的内存不足,那么就会有一部分数据会刷到磁盘中去
(3) MySQL 空闲的时候把数据进行刷盘
(4) 关闭数据库的时候,回刷数据回磁盘

而当要读入的数据页没有在内存的时候,就必须到缓冲池中申请一个数据页。这时候只能把最久不使用的数据页从内存中淘汰掉:

从上面我们可以看到redo log 的数据结构是一个环形的 ,这样 WAL 就变成了顺序写 ,提升了性能 .

redo 底层写了什么内容

下面图片和描述来自参考资料 ,非原创

redo 记录物理日志,记录的是“在某个数据页上做了什么修改”
例如下面的语句 :

update table set a = 1 where id = 1;

那么翻译成物理日志类似于这样 :

把第10表空间的第90号页面的偏移量为1024处的值更新为1

下面是大部分类型的redo log的通用结构:

1297993-20211007164148585-646595941.png

展示一下源码的数据结构的样子

struct alignas(INNOBASE_CACHE_LINE_SIZE) log_t {
    atomic_sn_t sn;                       // 目前log buffer申请的空间大小
    aligned_array_pointer<byte, OS_FILE_LOG_BLOCK_SIZE> buf;  // log buffer的内存区
    Link_buf<lsn_t> recent_written;               // 解决并发插入Redo Log Buffer后刷入ib_logfile存在空洞的问题
    Link_buf<lsn_t> recent_closed;        // 解决并发插入flush_list后确认checkpoint_lsn的问题
    atomic_lsn_t write_lsn;           // write_lsn之前的数据已经写入系统的Cache, 但不保证已经Flush
    atomic_lsn_t flushed_to_disk_lsn;         // 已经被flush到磁盘的数据
    size_t buf_size;                  // log buffer缓冲区的大小
    lsn_t available_for_checkpoint_lsn;      // 在此lsn之前的所有被添加到buffer pool的flush list的log数据已经被flsuh, 下一次checkpoint可以make在这个lsn. 与last_checkpoint_lsn的区别是该lsn尚未被真正的checkpoint.
    lsn_t requested_checkpoint_lsn;     // 下次需要进行checkpoint的lsn
    atomic_lsn_t last_checkpoint_lsn;       // 目前最新的checkpoint的lsn
    uint32_t write_ahead_buf_size;      // write ahead的Buffer大小
    lsn_t current_file_lsn;         // 
    uint64_t current_file_real_offset;      //
    uint64_t current_file_end_offset;       // 当前ib_logfile文件末尾的offset
    uint64_t file_size;             // 当前ib_logfile的文件大小
}

Redo log类型

先看一下 redo log 的基础类型
redo log类型主要是通过上面记录中的type体现的。比较基础的有以下几个(基础的类似于java里面的基本类型):

现在举一个例子。我们大部分情况下用的自增主键id都是int型或者是long型的,int为四个字节,long为八个字节,现在如果插入一条数据的话,这条数据实际是修改在buffer pool中的,然后通过redo log记录下当前的修改情况。那么这个时候,插入一条id(int)为9的数据的redo log应该是这样子的。

1297993-20211007164644410-1745186052.png

插入数据后 , 含义: 在90表空间,编号为10页面,偏移量为1000处,写入四个字节,具体数据为0000 0000 0000 1001
其他类型的 redo log 这里不再深入 ,这里仅做抛砖引玉 ,方便大家理解 redo log 记录的内容是什么

其他

MySQL 的 master 线程执行事件

MySQL 的 master 线程执行事件如下 :
图例

问题

脏页 和 redo log 的关系 ?

当客户端第一次开始查询数据的时候,数据由于不存在 buffer pool ,那么数据会从磁盘加载数据到
buffer pool ,然后返回给客户端; 当客户端第二条语句是更改语句,那么MySQL 此时会

redo log 和 bin log 的区别

小结

使用 redo log 是利用WAL(先写日志)技术,数据库将随机写转换成了顺序写,大大提升了数据库的性能。同事也可以保证事务的持久性, 保证事务持久性并不单单只有redo log,其实还有mysql的重要机制——double write,见这一篇文章

参考资料

标签:log,lsn,redo,checkpoint,MySQL,数据
来源: https://www.cnblogs.com/Benjious/p/15377251.html