共计 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 是什么”这篇文章就分享到这里了,希望以上内容可以对大家有一定的帮助,使各位可以学到更多知识,如果觉得文章不错,请把它分享出去让更多的人看到。