ICode9

精准搜索请尝试: 精确搜索
首页 > 数据库> 文章详细

MySQL学习(十)redo log 介绍

2021-10-07 22:04:18  阅读:274  来源: 互联网

标签:log lsn redo checkpoint MySQL 数据


前言

我们将从缓冲池开始介绍 ,然后后面开始介绍了 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

  • type:redo log的类型,目前redo log的类型很多
  • Space ID:表空间ID
  • page number:页号
  • data:一条redo log的内容

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

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里面的基本类型):

  • MLOG_1BYTE:type字段对应的十进制为1,表示在页面的某个偏移量处写入一个字节
  • MLOG_2BYTES:type字段对应的十进制为2,表示在页面的某个偏移量处写入两个字节
  • MLOG_4BYTES:type字段对应的十进制为4,表示在页面的某个偏移量处写入四个字节
  • MLOG_8BYTES:type字段对应的十进制为8,表示在页面的某个偏移量处写入八个字节
  • MLOG_WRITE_STRING::type字段对应的十进制为30,表示在页面的某个偏移量处写入一串数据

现在举一个例子。我们大部分情况下用的自增主键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 日志
    这样就形成了脏页,那么脏页和磁盘中的干净页是不一致的,脏页需要flush回磁盘才能达到持久化,flush 的过程必定会导致
  • 脏页变成了干净页
  • checkpoint 向前一步推进

redo log 和 bin log 的区别

  • redo log是InnoDB引擎特有的;binlog是MySQL的Server层实现的,所有引擎都可以使用。

  • redo log是物理日志,记录的是“在某个数据页上做了什么修改”;binlog是逻辑日志,记录的是这个语句的原始逻辑,比如“给ID=2这一行的c字段加1 ”。

  • redo log是循环写的,空间固定会用完;binlog是可以追加写入的。“追加写”是指binlog文件写到一定大小后会切换到下一个,并不会覆盖以前的日志。

小结

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

参考资料

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

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有