MySQL和DM8 redo log和存储过程机制区别

基于MySQL理解DM redo log机制初解

一、Redo Log是什么?

redo log 是物理日志,记录了某个数据页做了什么修改,对 XXX 表空间中的 YYY 数据页 ZZZ 偏移量的地方做了AAA 更新,每当执行一个事务就会产生这样的一条物理日志。 redo log 记录了某次事务「完成后」的数据状态,记录的是更新之「后」的值;

二、为什么需要Redo Log?

保证在数据库不正常关闭时,能准确恢复所有数据。

数据的更新修改都在放在内存里(Buffer Pool来完成的,然而内存总是不可靠,加之将内存中的数据写入到磁盘需要时间,万一在写入的时间内断电重启大概率事件),还没来得及落盘的脏页数据就会丢失。

为了防止断电导致数据丢失的问题,当有一条记录需要更新的时候,数据库就会先把这条记录的更新情况写到 redo log 里面,形成一条物理日志,再根据某种日志刷盘策略将redo log刷到磁盘中(日志的刷盘比数据的刷盘快很多),这样,即使断电重启,我们仍可以通过磁盘上的Redo Log日志进行数据的恢复。

三、Redo Log工作流程

在MySQL中称之为Write Ahead Log策略WAL)。

大致流程:

  1. 执行一条更新修改SQL;
  2. 将对应数据所在的数据页从磁盘读到BUFFER POOL缓冲池;
  3. 按照SQL命令修改数据,此时生成一条物理日志,并写入到redo log buffer中的redo log中。
  4. 当事务提交时COMMIT,会将redo log buffer中的redo log 刷到OS CACHE(文件缓存系统)【注:有不同日志刷盘策略】
  5. 再fsync从内存的OS Buffer数据永久写到系统磁盘上。【注:有不同机制】
  6. 将BUFFER POOL里的脏页刷新到磁盘上。【注:有不同机制】

⭐⭐⭐任何数据页从内存缓冲区写入磁盘之前,必须保证其对应的 REDO 日志已经写入到联机日志文件。 

四、工作流环节详解:日志刷盘

4.1 Redo log结构

Redo 日志包(RLOG_PKG)是 DM 数据库保存 Redo 日志的数据单元,一个日志包内可保存一个或多个 PTX 产生的 Redo 日志。

日志包具有自描述的特性,日志包大小固定,采用固定包头和可变包头结合的方式:包头记录日志的控制信息,包括类型、长度、包序号、 LSN 信息、产生日志的节点号、加密压缩信息、日志并行数等内容。日志包生成时按照序号连续递增,相邻日志包的 LSN 顺序是总体递增的,但是在 DMDSC 集群环境下不一定连续。如果未开启并行日志,RLOG_PKG 包内日志的 LSN 是递增的。如果开启并行日志,一个 RLOG_PKG 包内包含多路并行产生的日志,每一路并行日志的 LSN是递增的,但是各路之间的 LSN 并不能保证 LSN 有序,因此并行日志包内 LSN 具有局部有序,整体无序的特点。

redo log 是循环写的方式有序),相当于一个环形简略图如下:

那怎么知道该往哪里记录数据呢?大概如下图所示:(以MySQL为例)

图中的:

  1. write pos 和 checkpoint 的移动都是顺时针方向;
  2. write pos ~ checkpoint 之间的部分(图中的红色部分),用来记录新的更新操作;
  3. check point ~ write pos 之间的部分(图中蓝色部分):待落盘的脏数据页记录;

如果 write pos 追上了 checkpoint,就意味着 redo log 文件满了,这时 MySQL 不能再执行新的更新操作,也就是说 MySQL 会被阻塞(因此所以针对并发量大的系统,适当设置 redo log 的文件大小非常重要),此时会停下来将 Buffer Pool 中的脏页刷新到磁盘中,然后标记 redo log 哪些记录可以被擦除,接着对旧的 redo log 记录进行擦除,等擦除完旧记录腾出了空间,checkpoint 就会往后移动(图中顺时针),然后 MySQL 恢复正常运行,继续执行新的更新操作。

所以,一次 checkpoint 的过程就是脏页刷新到磁盘中变成干净页,然后标记 redo log 哪些记录可以被覆盖的过程。

4.2 联机重做日志文件

DM 数据库默认包含两个扩展名为 log 的Redo Log文件,存在于磁盘上,用来保存 REDO 日志,称为联机重做日志文件,这两个文件循环使用。(MySQL也一样,大概像这样):

重做日志文件组是以循环写的方式工作的,从头开始写,写到末尾就又回到开头,相当于一个环形。当log_file1 文件被写满的时候,会切换至log_file2 文件,当log_file2 文件也被写满时,会切换回log_file1 文件。

4.3 日志刷盘策略

触发机制:当事务提交、Redo日志包满、执行检查点时会进行日志刷盘。

4.4 Redo Log Buffer中日志结构(MySQL)

  1. 对底层页面的一个原子访问称为一个mtr,即迷你事务(Mini-Transaction
  2. 一个MTR包含一组redo日志,这一组日志是不可分割的一个整体(即使系统崩溃也不可分割)
  3. 一个事务可以包含若干个MTR,一个MTR可以包含若干个redo日志:

注:一个事务包含多个MTR,虽说redo日志是顺序写入的,但MTR之间的一组redo日志是没有顺序的。

  • 关键知识点:LSN序列号

5.1 概念

是日志的逻辑序列号,在InnoDB存储引擎中,LSN的值会随着日志的写入而逐渐增大。新的日志LSN等于旧的LSN加上新增日志的大小。

5.2 分类

每个页面都有 LSN,重做日志redo-log也有 LSN,检查点checkpoint也有 LSN。通过如下命令查看:SELECT * FROM SYS."V$RLOG";

  1. CUR_LSN 是系统已经分配的最大 LSN 值。物理事务提交时,系统会为其分配一个唯一的 LSN 值,大小等于 CUR_LSN + 1,然后再修改 CUR_LSN=CUR_LSN+1
  2. FLUSH_LSN 是已经发起日志刷盘请求,但还没有真正写入联机 Redo 日志文件的 最大 LSN 值。
  3. FILE_LSN 是已经写入联机 Redo 日志文件的最大 LSN 值。每次将 Redo 日志包 RLOG_PKG 写入联机 Redo 日志文件后,都要修改 FILE_LSN 值。
  4. CKPT_LSN 是检查点 LSN,所有 LSN <= CKPT_LSN 的物理事务修改的数据页,都已经从 Buffer 缓冲区写入磁盘,CKPT_LSN 由检查点线程负责调整。数据库故障重启时,CKPT_LSN 之前的 REDO 日志不需要重做,只需要从 CKPT_LSN+1 开始重做 REDO 日志,就可以将系统恢复到故障前状态。并且,在联机重做日志文件中,LSN<=CKPT_LSN REDO 日志都可以被覆盖。

对于系统来说,以上4个LSN是递减的,即: CUR_LSN >=FILE_LSN>=FLUSH_LSN>=CKPT_LSN.

5.3 LSN存储位置:(与上图对应)

  1. 在数据页面(内存与磁盘)存储LSN
  2. 在重做日志redo-log(内存)存储LSN
  3. 在重做日志redo-log(磁盘)存储LSN
  4. Checkpoint对应的LSN也是存储在重做日志记录中

5.4 LSN更新顺序

第一步:先写内存数据页面(内存的数据页面有LSN字段)

第二步:然后写缓冲内存的重做日志redo-log(内存的重做日志redo-log记录有LSN字段)

第三步:最后提交时重做日志redo-log进磁盘文件(磁盘的redo-log日志记录有pageLSN字段)

六、工作流环节详解:脏页刷盘checkpoint

Checkpoint所做的事情无外乎是将缓冲池中的脏页刷回到磁盘,不同之处在于每次刷新多少页到磁盘,每次从哪里取脏页,以及什么时间触发Checkpoint。

检查点(checkpoint)是一个数据库事件,它的功能是按照数据页的修改顺序,依次

BUFFER 缓冲区中的脏页写入磁盘,并在这个过程中动态调整 CKPT_LSN 值,释放日志空间。DM 的检查点分为两种:完全检查点和部分检查点:

ü 完全检查点:会将内存缓冲区中的所有脏页写入磁盘,并调整 CKPT_LSN,在数

据库正常关闭时会产生一个完全检查点。

ü 部分检查点 : 根 据 dm.ini 配 置 文 件 中 的 参 数 CKPT_FLUSH_RATE

CKPT_FLUSH_PAGES,确定每次检查点刷脏页的数量。执行部分检查点的过程中,DDL/DML

操作都可以正常执行,DM 系统中绝大多数情况下触发的都是部分检查点。数据库运行过程中产生的待写入日志首先写入 Redo 日志包 RLOG_PKG,当日志刷盘时一起写入联机日志文件中。在联机日志文件中,可以覆盖写入 REDO 日志的文件长度为可用日志空间;不能被覆盖的 REDO 日志,系统故障重启需要重做的 REDO 日志为有效日志,有效日志的 LSN 取值范围是(CKPT_LSN,FILE_LSN]

MySQLcheckpoint机制参考学习地址:

深入理解MySQL——关于checkpoint机制_mysql checkpoint-CSDN博客

七、Redo Log工作流程中LSN变化简图

假设现在BUFFER POOL里的脏页全部刷到磁盘上了,此时磁盘上数据页的最大LSN、内存里的redo log上的最大LSN、磁盘里的redo log上的最大LSN都一致,为LSN0。

现执行一条更新SQL语句,恰好对应数据页上的LSN就是LSN0(便于解释):

  1. 对应数据页被读到缓存池;
  2. 当数据被修改后,会生成相应的物理日志,该日志上会生成新的LSN1,该LSN1=LSN+1,即此时CUR_LSN = LSN1,于此同时,缓存池上被修改的数据也上的LSN也更新为LSN1.
  3. 在第二步的基础上,一个事务中如果有多个SQL更新语句,那么会生成多个物理日志,即包含了多个LSN,如LSN2/LSN3/LSN4/LSN5..../LSNn,对应缓存池上的数据页也会记录对应的LSN号。此时CUR_LSN = LSNn
  4. 事务提交时,假设所有新的日志刷盘到磁盘上,如果此时进度是50%,那么LSN1~LSN?已经刷到磁盘了,FLUSH_LSN = LSNn,FILE_LSN = LSN?。如果此时进度是100%,那么FLUSH_LSN = LSNn,FILE_LSN = LSNn
  5. 日志刷新到磁盘上后,如果还没出发checkpoint机制,此时CKPT_LSN = LSN0.
  6. 当触发checkpoint机制时,现在缓存池上的LSN都比LSN0大,说明都是脏页,那么就把这些数据写入磁盘,写入过程中,自然就把更新后的LSN带到磁盘数据页上了。

实际问题1:怎么判断脏页?

只需要判断缓存池中的数据页LSN值,如果LSN值大于 Checkpoint的LSN值,说明这个数据页接受了新的更新,那么这个页面就是脏页。

实际问题2:基于Checkpoint如何从crash中恢复?

MySQL在崩溃恢复时,会从重做日志redo-log的Checkpoint处开始执行重放操作。 它从CKPT_LSN开始扫描redo-log日志,并将其应用到buffer pool中,直到CKPT_LSN等于FILE_LSN (也就是redo-log磁盘上存储的LSN值),则恢复完成 。

  • 28
    点赞
  • 32
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值