MySQL事务中的redo与undo

MySQL事务中的redo与undo

一 前言

​ 众所周知InnoDB 是一个事务性的存储引擎,在上一小节我们提到事务有4种特性:原子性、一致性、隔离性和持久性,在事务中的操作,要么全部执行,要么全部不做,这就是事务的目的。

​ 那么事务的四种特性到底是基于什么机制实现呢???

  • 1、事务的原子性、隔离性由锁机制实现,我们将在后续章节《数据库锁机制》中介绍

  • 2、而事务的一致性和持久性由事务的 redo 日志和undo 日志来保证。

    redo log 是重做日志,提供再写入操作,实现事务的持久性;
    undo log 是回滚日志,提供回滚操作,保证事务的一致性。

本文将讨论关于事务中的redo和undo的几个问题:

  • redo 日志与undo日志分别用于记录什么?
  • redo 如何保证事务的持久性?
  • undo 如何保证事务的一致性?
  • undo log 是否是redo log的逆过程?

二 Redo log

2.1 redo的作用

记录的是尚未完成的操作,数据库崩溃则用其重做

2.2 redo的组成

Redo log可以简单分为以下两个部分:

  • 保存在内存中重做日志的缓冲 (redo log buffer),是易失的
  • 保存在硬盘中重做日志文件 (redo log file),是持久的

2.3 redo工作流程

InnoDB 的更新操作采用的是 Write Ahead Log (预先日志持久化)策略,即先写日志,再写入磁盘。

当一条记录更新时,redo流程大致如下

在内存更新数据后,会把更新后的记录写入到 redo log buffer 中。

第一步:InnoDB 会先把记录从硬盘读入内存
第二部:修改数据的内存拷贝
第三步:生成一条重做日志并写入redo log buffer,记录的是数据被修改后的值
第四步:当事务commit时,将redo log buffer中的内容刷新到 redo log file,对 redo log file采用追加写的方式
第五步:定期将内存中修改的数据刷新到磁盘中(注意注意注意,不是从redo log file刷入磁盘,而是从内存刷入磁盘,redo log file只在崩溃恢复数据时才用),如果数据库崩溃,则依据redo log buffer、redo log file进行重做,恢复数据,这才是redo log file的价值所在

2.4 Write Ahead Log

redo是如何保证事务的持久性的呢???

答案是Force Log at Commit 机制,即当事务commit提交时,innodb引擎先将 redo log buffer 写入到 redo log file 进行持久化,待事务的commit操作完成时才算完成。这种做法也被称为 Write-Ahead Log(预先日志持久化),在持久化一个数据页之前,先将内存中相应的日志页持久化。

问题1:为何不直接将修改的数据写入磁盘,而是要write ahead log呢?

答案:用于崩溃恢复
详解:
undo日志是对原始数据的备份
redo日志是对原始数据的修改

原始数据的按照既定的数据结构存放在磁盘上,写入磁盘是要耗费巨大成本的,而写入redo相对容易一些,因为redo里毕竟只需要考虑存放改动的数据即可,所以内存数据写写入redo log file,然后内存数据才能写入磁盘,如此,在内存数据再写入磁盘时因为某种原因比如断电崩溃,那么还可以依据redo log file恢复数据,如下图所示。

问题2:如何保证每次修改的数据都能写入redo log file呢?

# 储备知识1
O_DIRECT选项是在Linux系统中的选项,使用该选项后,对文件进行直接IO操作,不经过文件系统缓存,直接写入磁盘

# 储备知识2
redo log又称之为重做日志,因重做日志打开并没有O_DIRECT选项,所以重做日志先写入到文件系统缓存,然后才会刷入硬盘,即
Redo log buffer--->os cache(文件系统缓存)--->redo log file

如果在刷入redo log file前断电,则会丢失文件系统缓存中数据,数据未写入redo log file,
因为由内存写入redo log file在前,而由内存写入磁盘在后,所以redo log file写入失败,则数据丢失

# 那如何保证每次的修改都记入日志文件redo log file呢???
答案是fsync操作
在每次将redo buffer写入os cache文件系统缓存后,InnoDB存储引擎都需要调用一次 fsync操作,保证立即由os cache文件系统缓存写入redo log file

fsync是一种系统调用操作,其fsync的效率取决于磁盘的性能,因此磁盘的性能也影响了事务提交的性能,也就是数据库的性能。

问题3:脏页何时刷入磁盘呢?

# 储备知识:脏页
Buffer Pool 中更新的数据未刷新到磁盘中,该内存页我们称之为脏页。最终脏页的数据会刷新到磁盘中,将磁盘中的数据覆盖,这个过程与 redo log 不一定有关系。

# 答案
redo log 日志满了的情况下,会主动触发脏页刷新到磁盘

问题4:脏页只在redo log满的情况下才会刷入磁盘吗?

答案:no,以下几种情况同样会触发脏页的刷新

- 1、系统内存不足时,需要将一部分数据页淘汰掉,如果淘汰的是脏页,需要先将脏页同步到磁盘;
- 2、MySQL 认为空闲的时间,这种情况没有性能问题;
- 3、MySQL 正常关闭之前,会把所有的脏页刷入到磁盘,这种情况也没有性能问题。

问题5:脏页刷入会带来性能问题吗?

联系管理员微信tutu19192010,注册账号

上一篇
下一篇
Copyright © 2022 Egon的技术星球 egonlin.com 版权所有 帮助IT小伙伴学到真正的技术