MySQL事务日志——REDO日志、UNDO日志详解

文章详细介绍了MySQL数据库中REDO日志和UNDO日志的作用和机制。REDO日志用于保证事务的持久性,先写入日志再写入磁盘,确保即使内存数据丢失也能恢复;UNDO日志则确保事务的原子性和一致性,记录事务更新前的数据,以便在回滚时恢复原状。通过innodb_flush_log_at_trx_commit参数控制REDO日志的刷盘策略,以平衡性能与数据安全性。
摘要由CSDN通过智能技术生成

0、前言

        本文将详细介绍MySQL数据库中的REDO日志的作用、实现了什么功能、具体机制和优缺点。需要具有一定的数据库基础、熟悉事务的ACID的前提下可以更好地阅读😄

        对于事务,我们知道有原子性、一致性、隔离性和持久性四种特性。
简单概括就是:

  1. 原子性:事务是最小的执行单位,不可再拆分了
  2. 一致性:对于事务的操作,要保证结果的一致。比如一边+了50,另一边减少50,则两边必须都完成or都没完成才可以,不能够只完成一部分。
  3. 隔离性:针对多线程并发情况,要保证一个事务在线程执行的过程中,不被别的线程所干扰、改动数据。
  4. 持久性:就是事务提交了 ,做完了,那这个数据就要持久地保存在磁盘里。不能说提交了结果后面发现数据没在里面,那就乱套了。

        事务的隔离性锁机制 实现。
        而事务的原子性、一致性和持久性由事务的 redo 日志和undo 日志来保证。
        REDO LOG 称为 重做日志 ,提供再写入操作,恢复提交事务修改的页操作,用来保证事务的持久性。
        UNDO LOG 称为 回滚日志 ,回滚行记录到某个特定版本,用来保证事务的原子性、一致性。

1、基础知识——缓冲池Buffer Pool与"刷盘"操作 

        InnoDB存储引擎操作数据库的时候 ,并不是直接通过sql语句对磁盘进行crud,因为直接操作磁盘会带来大量的 IO,以及效率和速度底下等问题。所以实际上,InnoDB是先将磁盘的数据加载到内存中,然后对内存进行crud以后,再通过checkpoint机制(按照一定的时间间隔进行刷盘)把做好的数据传回磁盘,也就是所谓“刷盘”

        对于这样的操作,虽然速度快了,但可靠性就会出问题。
        因为对于内存而言,并不能保证数据的持久化,如果发生断电、宕机的问题,内存中的数据就全都消失了!这样的结果必然是不可以容许的。
        例如,对于一个事务,已经做完并提交了,内存中的数据也操作完了,本来此时应该刷盘回磁盘,从而保证持久化,结果这时候数据库宕机了,那么这段数据就丢失了、无法恢复。

        那么该如何解决这种持久性的问题呢?使用REDO日志!

2、REDO日志

2.1 REDO日志的组成

        REDO日志其实包含2部分

(1)重做日志的缓冲 (redo log buffer),保存在内存中,容易丢失。其参数设置:innodb_log_buffer_size默认16M大小。

(2)重做日志的文件 (redo log file) ,保存在硬盘中,是持久的。

2.2 REDO日志的基本实现流程

        InnodeDB的更新操作采用Write Ahead Log的策略,关键就在于:先写入日志,再写入磁盘,即下图的顺序1、2、3、4。其具体解析如下。

        

第1步:先将原始数据从磁盘中读入内存中来,修改数据的内存拷贝。

第2步:生成一条重做日志并写入redo log buffer,记录的是数据被修改后的值。

第3步:当事务commit时将redo log buffer中的内容刷新到 redo log file,对 redo log file采用追加写的方式。

第4步:定期将内存中修改的数据刷新到磁盘。

解读

  • 对于前2步,需要注意:update事务每做1条,就要在redo log buffer中更改一条!而不是commit全部事务以后才更新redo log buffer。
            这样做的好处是,如果没有commit事务就发生宕机,那就全部数据丢失,但是无所谓!因为反正没commit的事务也不需要保存,丢失就对了!恰恰保证了事物的一致性
  • 对于第3步,需要注意:事务commit后,就要把内存中的redo内容刷入磁盘中的redo file,后期才方便恢复数据

        所以,REDO日志的核心思想就是:如果因为数据库宕机等问题导致内存丢失,但是具体操作已经存入redo file了,下次直接从磁盘的redo file恢复这次事务的操作即可。

2.3  redo log的刷盘策略(即上一小节的第3步)

        redo log的写入并不是直接写入磁盘的,InnoDB引擎会在写redo log的时候先写redo log buffer,之后以一定的频率刷入到真正的redo log file 中。这里的一定频率怎么看待呢?这就是我们要说的刷盘策略。

         注意,redo log buffer刷盘到redo log file的过程并不是真正的刷到磁盘中去,只是刷入到 文件系统缓存 (page cache)中去(这是现代操作系统为了提高文件写入效率做的一个优化),真正的写入会交给系统自己来决定(比如page cache足够大了)。
        那么对于InnoDB来说就存在一个问题,如果交给系统来同步,同样如果系统宕机,那么数据也丢失了(虽然整个系统宕机的概率还是比较小的)。


        针对这种情况,InnoDB给出 innodb_flush_log_at_trx_commit 参数,该参数控制 commit提交事务时,如何将 redo log buffer 中的日志刷新到 redo log file 中。它支持三种策略:

  • 设置为0 :表示每次事务提交时不进行刷盘操作。(系统默认master thread每隔1s进行一次重做日志的同步)
  • 设置为1 :表示每次事务提交时都将进行同步,刷盘操作( 默认值 )
  • 设置为2 :表示每次事务提交时都只把 redo log buffer 内容写入 page cache,不进行同步。由os自己决定什么时候同步到磁盘文件。(这种策略,就算数据库宕机了,但只要操作系统不挂掉,那么数据仍然会从page cache刷盘进去。)

3、基础知识:事务的回滚

         事务需要保证 原子性 ,也就是事务中的操作要么全部完成,要么什么也不做。

        但有时候事务执行到一半会出现一些情况,比如:
        情况一:事务执行过程中可能遇到各种错误,比如 服务器本身的错误 , 操作系统错误 ,甚至是突然断电导致的错误。
        情况二:程序员可以在事务执行过程中手动输入 ROLLBACK 语句结束当前事务的执行。

        以上情况出现,我们需要把数据改回原先的样子,这个过程称之为 回滚

4、UNDO日志

        相对于REDO日志文件记录的是update以后的数据,UNDO日志是用于记录update之前的数据(因为UNDO日志的作用就是恢复update之前的数据嘛,即回滚到之前的状态)。

4.1 作用

4.2 存储结构

    InnoDB对undo log的管理采用段的方式,也就是 回滚段(rollback segment) 。每个回滚段记录了 1024 个 undo log segment ,而在每个undo log segment段中进行 undo页 的申请。    

4.3 流程

(1)当一个事务开始的时候,会制定一个回滚段,在事务进行的过程中,当数据被修改时,原始的数据会先被复制到回滚段

(2.1)如果在commit之前执行回滚操作,MySQL会使用UNDO日志来撤销事务所做的所有update操作:

        回滚过程中使用的Undo日志记录了对数据进行修改或删除操作的信息,包括修改前的值和修改后的值。当执行回滚操作时,InnoDB会通过Undo日志将数据恢复到回滚之前的状态。

具体来说,Undo日志实现回滚的原理如下:

  1. 在开始一个事务之前,InnoDB会为该事务分配一块Undo日志区域,并记录该区域的起始位置。

  2. 当事务对一个数据进行修改时,InnoDB会将修改前的版本写入Undo日志中

  3. 当回滚操作发生时,InnoDB会遍历Undo日志中的记录,反向撤销所有对数据的修改操作,即将数据恢复到修改前的状态。

  4. 回滚操作完成后,InnoDB会将Undo日志标记为已使用,并在下次清理Undo日志时将其释放。

(2.2)如果在commit后执行回滚操作:

        当一个事务提交(commit)之后,MySQL会将该事务对应的Undo日志标记为“已提交”,但不会立即删除它。相反,它将继续存储在磁盘上,直到InnoDB的回收线程将其清理。

        这是因为Undo日志被用于实现MVCC(多版本并发控制)机制,以支持读已提交(read committed)和可重复读(repeatable read)隔离级别的事务。

        在可重复读隔离级别下,当一个事务提交后,它对应的Undo日志就像是一个时间点的快照一样,记录了此时事务对数据的修改前的状态。如果需要回滚该事务,MySQL就会使用这些Undo日志来将数据还原到提交之前的状态。

5、总结

         undo log是逻辑日志,对事务回滚时,只是将数据库逻辑地恢复到原来的样子。

         redo log是物理日志,记录的是数据页的物理变化,undo log不是redo log的逆过程

  • 1
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

好奇的7号

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值