mysql中undo log 及 redo log是什么

72次阅读
没有评论

共计 3499 个字符,预计需要花费 9 分钟才能阅读完成。

这篇文章将为大家详细讲解有关 mysql 中 undo log 及 redo log 是什么,丸趣 TV 小编觉得挺实用的,因此分享给大家做个参考,希望大家阅读完这篇文章后可以有所收获。

00 – Undo Log
Undo Log 是为了实现事务的原子性,在 MySQL 数据库 InnoDB 存储引擎中,还用 Undo Log 来实现多版本并发控制(简称:MVCC)。

– 事务的原子性 (Atomicity)
  事务中的所有操作,要么全部完成,要么不做任何操作,不能只做部分操作。如果在执行的过程中发生
  了错误,要回滚(Rollback) 到事务开始前的状态,就像这个事务从来没有执行过。

– 原理
  Undo Log 的原理很简单,为了满足事务的原子性,在操作任何数据之前,首先将数据备份到一个地方
 (这个存储数据备份的地方称为 Undo Log)。然后进行数据的修改。如果出现了错误或者用户执行了
  ROLLBACK 语句,系统可以利用 Undo Log 中的备份将数据恢复到事务开始之前的状态。

除了可以保证事务的原子性,Undo Log 也可以用来辅助完成事务的持久化。

– 事务的持久性(Durability)
  事务一旦完成,该事务对数据库所做的所有修改都会持久的保存到数据库中。为了保证持久性,数据库
  系统会将修改后的数据完全的记录到持久的存储上。

– 用 Undo Log 实现原子性和持久化的事务的简化过程
  假设有 A、B 两个数据,值分别为 1,2。
  A. 事务开始.
  B. 记录 A = 1 到 undo log.
  C. 修改 A =3.
  D. 记录 B = 2 到 undo log.
  E. 修改 B =4.
  F. 将 undo log 写到磁盘。
  G. 将数据写到磁盘。
  H. 事务提交
  这里有一个隐含的前提条件:‘数据都是先读到内存中,然后修改内存中的数据,最后将数据写回磁盘’。

  之所以能同时保证原子性和持久化,是因为以下特点:
  A. 更新数据前记录 Undo log。
  B. 为了保证持久性,必须将数据在事务提交前写到磁盘。只要事务成功提交,数据必然已经持久化。
  C. Undo log 必须先于数据持久化到磁盘。如果在 G,H 之间系统崩溃,undo log 是完整的,
      可以用来回滚事务。
  D. 如果在 A - F 之间系统崩溃, 因为数据没有持久化到磁盘。所以磁盘上的数据还是保持在事务开始前的状态。

缺陷:每个事务提交前将数据和 Undo Log 写入磁盘,这样会导致大量的磁盘 IO,因此性能很低。

如果能够将数据缓存一段时间,就能减少 IO 提高性能。但是这样就会丧失事务的持久性。因此引入了另外一
种机制来实现持久化,即 Redo Log.

01 – Redo Log

– 原理
  和 Undo Log 相反,Redo Log 记录的是新数据的备份。在事务提交前,只要将 Redo Log 持久化即可,
  不需要将数据持久化。当系统崩溃时,虽然数据没有持久化,但是 Redo Log 已经持久化。系统可以根据
  Redo Log 的内容,将所有数据恢复到最新的状态。

– Undo + Redo 事务的简化过程
  假设有 A、B 两个数据,值分别为 1,2.
  A. 事务开始.
  B. 记录 A = 1 到 undo log.
  C. 修改 A =3.
  D. 记录 A = 3 到 redo log.
  E. 记录 B = 2 到 undo log.
  F. 修改 B =4.
  G. 记录 B = 4 到 redo log.
  H. 将 redo log 写入磁盘。
  I. 事务提交

– Undo + Redo 事务的特点
  A. 为了保证持久性,必须在事务提交前将 Redo Log 持久化。
  B. 数据不需要在事务提交前写入磁盘,而是缓存在内存中。
  C. Redo Log 保证事务的持久性。
  D. Undo Log 保证事务的原子性。
  E. 有一个隐含的特点,数据必须要晚于 redo log 写入持久存储。

– IO 性能
  Undo + Redo 的设计主要考虑的是提升 IO 性能。虽说通过缓存数据,减少了写数据的 IO.
  但是却引入了新的 IO,即写 Redo Log 的 IO。如果 Redo Log 的 IO 性能不好,就不能起到提高性能的目的。
  为了保证 Redo Log 能够有比较好的 IO 性能,InnoDB 的 Redo Log 的设计有以下几个特点:

  A. 尽量保持 Redo Log 存储在一段连续的空间上。因此在系统第一次启动时就会将日志文件的空间完全分配。
      以顺序追加的方式记录 Redo Log, 通过顺序 IO 来改善性能。
  B. 批量写入日志。日志并不是直接写入文件,而是先写入 redo log buffer. 当需要将日志刷新到磁盘时
     (如事务提交), 将许多日志一起写入磁盘.
  C. 并发的事务共享 Redo Log 的存储空间,它们的 Redo Log 按语句的执行顺序,依次交替的记录在一起,
      以减少日志占用的空间。例如,Redo Log 中的记录内容可能是这样的:
    记录 1: trx1, insert …
    记录 2: trx2, update …
    记录 3: trx1, delete …
    记录 4: trx3, update …
    记录 5: trx2, insert …
  D. 因为 C 的原因, 当一个事务将 Redo Log 写入磁盘时,也会将其他未提交的事务的日志写入磁盘。
  E. Redo Log 上只进行顺序追加的操作,当一个事务需要回滚时,它的 Redo Log 记录也不会从
    Redo Log 中删除掉。

02 – 恢复(Recovery)

– 恢复策略
  前面说到未提交的事务和回滚了的事务也会记录 Redo Log,因此在进行恢复时, 这些事务要进行特殊的
  的处理. 有 2 中不同的恢复策略:

  A. 进行恢复时,只重做已经提交了的事务。
  B. 进行恢复时,重做所有事务包括未提交的事务和回滚了的事务。然后通过 Undo Log 回滚那些
    未提交的事务。

– InnoDB 存储引擎的恢复机制
  MySQL 数据库 InnoDB 存储引擎使用了 B 策略, InnoDB 存储引擎中的恢复机制有几个特点:

  A. 在重做 Redo Log 时,并不关心事务性。恢复时,没有 BEGIN,也没有 COMMIT,ROLLBACK 的行为。
      也不关心每个日志是哪个事务的。尽管事务 ID 等事务相关的内容会记入 Redo Log,这些内容只是被当作
    要操作的数据的一部分。
  B. 使用 B 策略就必须要将 Undo Log 持久化,而且必须要在写 Redo Log 之前将对应的 Undo Log 写入磁盘。
    Undo 和 Redo Log 的这种关联,使得持久化变得复杂起来。为了降低复杂度,InnoDB 将 Undo Log 看作
    数据,因此记录 Undo Log 的操作也会记录到 redo log 中。这样 undo log 就可以象数据一样缓存起来,
    而不用在 redo log 之前写入磁盘了。
    包含 Undo Log 操作的 Redo Log,看起来是这样的:
    记录 1: trx1, Undo log insert  undo_insert …
    记录 2: trx1, insert …
    记录 3: trx2, Undo log insert  undo_update …
    记录 4: trx2, update …
    记录 5: trx3, Undo log insert  undo_delete …
    记录 6: trx3, delete …
  C. 到这里,还有一个问题没有弄清楚。既然 Redo 没有事务性,那岂不是会重新执行被回滚了的事务?
    确实是这样。同时 Innodb 也会将事务回滚时的操作也记录到 redo log 中。回滚操作本质上也是
    对数据进行修改,因此回滚时对数据的操作也会记录到 Redo Log 中。
    一个回滚了的事务的 Redo Log,看起来是这样的:
    记录 1: trx1, Undo log insert undo_insert …
    记录 2: trx1, insert A…
    记录 3: trx1, Undo log insert undo_update …
    记录 4: trx1, update B…
    记录 5: trx1, Undo log insert  undo_delete …
    记录 6: trx1, delete C…
    记录 7: trx1, insert C
    记录 8: trx1, update B to old value
    记录 9: trx1, delete A
    一个被回滚了的事务在恢复时的操作就是先 redo 再 undo,因此不会破坏数据的一致性.

– InnoDB 存储引擎中相关的函数
  Redo: recv_recovery_from_checkpoint_start()
  Undo: recv_recovery_rollback_active()
  Undo Log 的 Redo Log: trx_undof_page_add_undo_rec_log()

关于“mysql 中 undo log 及 redo log 是什么”这篇文章就分享到这里了,希望以上内容可以对大家有一定的帮助,使各位可以学到更多知识,如果觉得文章不错,请把它分享出去让更多的人看到。

正文完
 
丸趣
版权声明:本站原创文章,由 丸趣 2023-07-26发表,共计3499字。
转载说明:除特殊说明外本站除技术相关以外文章皆由网络搜集发布,转载请注明出处。
评论(没有评论)