REDO LOG 与 UNDO LOG这两个概念的区别

本文深入探讨了数据库中的Redo与Undo日志机制,包括它们在事务提交过程中的作用、如何确保数据一致性以及在系统恢复时的应用。通过具体实例说明了这两种日志如何帮助实现事务的原子性和持久性。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

  转自:[url]http://www.cnblogs.com/jonescheng/archive/2008/05/08/1189063.html[/url]

redo log  重做日志/undo log   撤消日志
重做日志:每当有操作执行前,将数据真正更改时,先前相关操作写入重做日志。这样当断电,或者一些意外,导致后续任务无法完成时,系统恢复后,可以继续完成这些更改

撤消日志:当一些更改在执行一半时,发生意外,而无法完成,则可以根据撤消日志恢复到更改之前的壮态

网上找到一些解说:以便以后自己参考
有两个概念:前滚与回退
比如某一时刻数据库DOWN机了,有两个事务,一个事务已经提交,另一个事务正在处理
数据库重启的时候就要根据日志进行前滚及回退,把已提交事务的更改写到数据文件,未提交事务的更改恢复到事务开始前的状态。
 

redo--> undo-->datafile
insert一条记录时, 表跟undo的信息都会放进 redo 中, 在commit 或之前, redo 的信息会放进硬盘上. 故障时, redo 便可恢复那些已经commit 了的数据.

redo->每次操作都先记录到redo日志中,当出现实例故障(像断电),导致数据未能更新到数据文件,则数据库重启时须redo,重新把数据更新到数据文件
undo->记录更改前的一份copy,但你系统rollback时,把这份copy重新覆盖到原来的数据

redo->记录所有操作,用于恢复(redo records all the database transaction used for recovery)
undo->记录所有的前印象,用于回滚(undo is used to store uncommited data infor used for rollback)

redo->已递交的事务,实例恢复时要写到数据文件去的 
undo->未递交的事务.

redo的原因是:每次commit时,将数据的修改立即写到online redo中,但是并不一定同时将该数据的修改写到数据文件中。因为该数据已经提交,但是只存在联机日志文件中,所以在恢复时需要将数据从联机日志文件中找 出来,重新应用一下,使已经更改数据在数据文件中也改过来!

undo的原因是:在oracle正常运行时,为了提高效率,加入用户还没有commit,但是空闲内存不多时,会由DBWR进程将脏块写入到数据 文件中,以便腾出宝贵的内存供其它进程使用。这就是需要UNDO的原因。因为还没有发出commit语句,但是oracle的dbwr进程已经将没有提交 的数据写到数据文件中去了。

undo 也是也是datafile, 可能dirty buffer 没有写回到磁盘里面去。
只有先redo apply 成功了,才能保证undo datafile 里面的东西都是正确的,然后才能rollback

做undo的目的是使系统恢复到系统崩溃前(关机前)的状态,再进行redo是保证系统的一致性. 
不做undo,系统就不会知道之前的状态,redo就无从谈起

所以instance crash recovery 的时候总是先rollforward, 再rollback

undo
回退段中的数据是以“回退条目”方式存储。
回退条目=块信息(在事务中发生改动的块的编号)+在事务提交前存储在块中的数据

在每一个回退段中oracle都为其维护一张“事务表”
在事务表中记录着与该回退段中所有回退条目相关的事务编号(事务SCN&回退条目)

redo
重做记录由一组“变更向量”组成。
每个变更变量中记录了事务对数据库中某个块所做的修改。
当用户提交一条commit语句时,LGWR进程会立刻将一条提交记录写入到重做日志文件中,然后再开始写入与该事务相关的重做信息。

#事务提交成功后,Oracle将为该事备生成一个系统变更码(SCN)。事务的SCN将同时记录在它的提交记录和重做记录中。

commit
提交事务前完成的工作:
·在SGA区的回退缓存中生成该事务的回退条目。在回退条目中保存有该事务所修改的数据的原始版本。
·在SGA区的重做日志缓存中生成该事务的重做记录。重做记录中记载了该事务对数据块所进行的修改,并且还记载了对回退段中的数据块所进行的修改。缓存中的重做记录有可能在事务提交之前就写入硬盘中。
·在SGA区的数据库缓丰中记录了事务对数据库所进行的修改。这些修改也有可能在事务提交之前就写入硬盘中。

提交事务时完成的工作:
·在为该事务指定的回退段中的内部事务表内记录下这个事务已经被提交,并且生成一个惟一的SCN记录在内部事务表中,用于惟一标识这个事务。
·LGWR后进进程将SGA区重做日志缓存中的重做记录写入联机重做日志文件。在写入重做日志的同时还将写入该事务的SCN。
·Oracle服务进程释放事务所使用的所有记录锁与表锁。
·Oracle通知用户事务提交完成。
·Oracle将该事务标记为已完成。

rollback
回退事务完成的工作:
·Oracle通过使用回退段中的回退条目,撤销事务中所有SQL语句对数据库所做的修改。
·Oracle服务进程释放事务所使用的所有锁
·Oracle通知事务回退成功。
·Oracle将该事务标记为已完成

举个例子:
insert into a(id) values(1);(redo)
这条记录是需要回滚的。
回滚的语句是delete from a where id = 1;(undo)

试想想看。如果没有做insert into a(id) values(1);(redo)
那么delete from a where id = 1;(undo)这句话就没有意义了。

现在看下正确的恢复:
先insert into a(id) values(1);(redo)
然后delete from a where id = 1;(undo)
系统就回到了原先的状态,没有这条记录了。

 

===============================

 

http://blog.youkuaiyun.com/leonpenn/article/details/72778901

为了最大程度避免数据写入时io瓶颈带来的性能问题,MySQL采用了这样一种缓存机制:当query修改数据库内数据时,InnoDB先将该数据从磁盘读取到内存中,修改内存中的数据拷贝,并将该修改行为持久化到磁盘上的事务日志(先写redo log buffer,再定期批量写入),而不是每次都直接将修改过的数据记录到硬盘内,等事务日志持久化完成之后,内存中的脏数据可以慢慢刷回磁盘,称之为Write-Ahead Logging。事务日志采用的是追加写入,顺序io会带来更好的性能优势。

为了避免脏数据刷回磁盘过程中,掉电或系统故障带来的数据丢失问题,InnoDB采用事务日志(redo log)来解决该问题。

 

【redo log】

用于在实例故障恢复时,继续那些已经commit但数据尚未完全回写到磁盘的事务。

The redo log is a disk-based data structure used during crash recovery to correct data written by incomplete transactions. 

通常会初始化2个或更多的 ib_logfile 存储 redo log,由参数 innodb_log_files_in_group 确定个数,命名从 ib_logfile0 开始,依次写满 ib_logfile 并顺序重用(in a circular fashion)。如果最后1个 ib_logfile 被写满,而第一个ib_logfile 中所有记录的事务对数据的变更已经被持久化到磁盘中,将清空并重用之。

在写入量比较高的情况下,redo log 的大小将显著地影响写入性能。

innodb_log_file_size 用来控制 ib_logfile 的大小。5.5版本及以前:默认5MB,最大4G。

所有事务日志累加大小不超过4G,事务日志过大,checkpoint会减少,在节省磁盘io的同时,大的事务日志也意味着数据库crash后,恢复起来较慢。

官方文档建议innodb_log_file_size的设置可参考 show engine innodb status \G

Log sequence number -Last checkpoint < (innodb_log_files_in_group * innodb_log_file_size ) * 0.75

 

【undo log】

记录了数据修改的前镜像。存放于ibdata中。(提一句,DDL操作会修改数据字典,该信息也存放在ibdata中)

用于在实例故障恢复时,借助undo log将尚未commit的事务,回滚到事务开始前的状态。

转载于:https://my.oschina.net/newchaos/blog/1579647

<think>我们正在讨论MySQL的UndoLogRedoLog区别。用户明确要求比较这两种日志的差异,因此我们需要从多个维度进行对比分析。以下是我对两种日志的理解:首先,UndoLogRedoLog在MySQL中都是InnoDB存储引擎实现事务特性的关键组件,但它们的功能和设计目标完全不同。UndoLog(回滚日志)的核心作用是支持事务回滚和MVCC(多版本并发控制):-当事务对数据进行修改时,会先将修改前的旧值写入UndoLog-如果事务需要回滚,就可以根据UndoLog中的记录将数据恢复到修改前的状态-UndoLog还用于实现MVCC,当其他事务需要读取历史版本数据时,可以通过UndoLog链访问RedoLog(重做日志)则主要解决持久性问题:-记录的是物理修改(如"在某个数据页的某个偏移量做了何种修改")-采用WAL(Write-AheadLogging)机制,即先写日志再写磁盘-确保即使数据库崩溃,已提交的事务修改也不会丢失接下来我们可以从七个维度详细对比:1.**核心目的**-UndoLog:实现事务的**原子性**(回滚)和**隔离性**(MVCC)-RedoLog:保证事务的**持久性**2.**记录内容**-UndoLog:逻辑日志(如"UPDATE前的行数据")-RedoLog:物理日志("在page_no=5的页中偏移量offset=100处写入'ABC'")3.**生命周期**-UndoLog:在事务提交后不会立即删除(因为MVCC可能需要),由后台purge线程清理-RedoLog:写入后当对应的脏页刷盘,其空间可被循环复用4.**存储位置**-UndoLog:默认存储在全局表空间(ibdata1)或独立的undo表空间-RedoLog:固定大小的循环文件(通常ib_logfile0,ib_logfile1)5.**写入时机**-UndoLog:在事务修改数据**前**写入-RedoLog:在事务提交时按策略刷盘(innodb_flush_log_at_trx_commit控制)6.**恢复作用**-UndoLog:崩溃恢复时回滚未提交事务-RedoLog:重做已提交但未刷盘的事务7.**空间管理**-UndoLog:需要定期purge,长时间未提交的事务可能导致膨胀-RedoLog:循环写入,空间固定最后考虑用表格形式清晰展示这些差异,并添加一个简短的总结说明两者的协同工作关系(比如在崩溃恢复时如何配合)。同时准备相关问题,如日志优化、配置参数等延伸话题。</think>### MySQL Undo Log vs Redo Log 核心区别详解 #### 一、核心目的差异 | **日志类型** | **核心目的** | 实现机制 | |--------------|-----------------------------|----------------------------| | **Undo Log** | 保证**原子性**(回滚能力) | 记录修改前的数据状态,用于事务回滚[^1] | | **Redo Log** | 保证**持久性**(崩溃恢复) | 记录修改后的物理操作,用于重做提交事务[^3] | #### 二、数据结构内容差异 **1. Undo Log 结构** - **逻辑日志**:记录反向操作语句(如`INSERT`对应`DELETE`) - 存储格式: ``` [事务ID][回滚指针][修改前数据镜像] ``` - 组成**版本链**:通过`DB_ROLL_PTR`链接历史版本,支持MVCC[^4] **2. Redo Log 结构** - **物理日志**:记录数据页的物理修改(如"页号5偏移量100写入'ABC'") - 存储格式: ```plaintext [LSN(日志序列号)][Page ID][Offset][修改内容] ``` - **循环写入**:固定大小文件(默认`ib_logfile0/1`),覆盖旧记录[^3] #### 三、写入时机生命周期 | **特性** | **Undo Log** | **Redo Log** | |----------------|----------------------------|----------------------------| | **写入时机** | 数据修改**前**写入 | 数据修改**后**,提交**前**写入 | | **持久化要求** | 事务提交后延迟清理 | 事务提交时**强制刷盘** | | **生命周期** | 直到无事务需要MVCC版本才清除 | 对应脏页刷盘后即可覆盖 | #### 四、崩溃恢复中的作用 1. **Undo Log 恢复流程** $$ \text{Rollback} = \text{Apply Undo Records} $$ - 回滚未提交事务 - 重建历史版本数据 2. **Redo Log 恢复流程** $$ \text{Recovery} = \text{Replay Redo Log from Checkpoint} $$ - 重做所有已提交事务 - 确保数据不丢失(即使未刷入数据文件)[^3] #### 五、存储位置管理 | **维度** | **Undo Log** | **Redo Log** | |---------------|----------------------------------|----------------------------------| | **存储位置** | 共享表空间(`ibdata1`)或独立undo表空间 | 独立文件(`ib_logfile0`, `ib_logfile1`) | | **空间管理** | 需要定期`purge`防止膨胀 | 固定大小循环写入 | | **配置参数** | `innodb_undo_tablespaces` | `innodb_log_file_size` | #### 六、协同工作示例(事务提交) ```mermaid sequenceDiagram 事务->>Buffer Pool: 修改数据页 Buffer Pool->>Undo Log: 写入修改前镜像(原子性) Buffer Pool->>Redo Log Buffer: 写入物理操作(持久性) 事务提交->>Redo Log: 刷盘(innodb_flush_log_at_trx_commit=1) Redo Log->>数据文件: 异步刷脏页 ``` #### 七、关键总结 | **对比维度** | **Undo Log** | **Redo Log** | |---------------|--------------------|--------------------| | **核心特性** | 逻辑日志/回滚 | 物理日志/重做 | | **ACID侧重** | 原子性(A)+隔离性(I) | 持久性(D) | | **空间影响** | 可能膨胀需清理 | 固定大小循环覆盖 | | **性能优化** | 缩短事务减少版本链 | 增大日志文件减少刷盘 | > **典型场景**: > 当执行`UPDATE user SET balance=200 WHERE id=1`: > - Undo Log 记录:`(tx_id=101, balance=100)` > - Redo Log 记录:`(LSN=2024, Page=5, Offset=120, Value=200)` > 若事务回滚:通过Undo恢复`balance=100`[^1] > 若崩溃恢复:通过Redo重做`balance=200`[^3]
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值