当前位置:文档之家› REDO LOG 与 UNDO LOG这两个概念的区别

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

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

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

转自:

[url]https://www.doczj.com/doc/d218534699.html,/jonescheng/archive/2008/05/08/1189063.ht ml[/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,再rollbackundo

回退段中的数据是以“回退条目”方式存储。

回退条目=块信息(在事务中发生改动的块的编号)+在事务提交前存储在块中的数据在每一个回退段中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)

系统就回到了原先的状态,没有这条记录了

16.1.4 日志文件(Redolog Files)

在Oracle数据库环境下流传着这样一句话:要想知道数据库曾经都做过什么,问问重做日志文件就知道!人们是这样说,重做日志文件也是这样做的。重做日志文件为什么能做到这一点,又是如何数十年如一日,始终保持重做日志组成员先进性的呢?这一切,要从重做日志文件的名字说起……

重做有一个好听的英文名字叫Redo,特指一项操作。在Oracle数据库中,执行数据修改操作后,并不是马上写入数据文件,而是首先生成重做信息,并写入SGA中的一块叫LOG_BUFFER(关于这部分内容将在介绍实例的体系结构时详细阐述)的固定区域,LOG_BUFFER的空间并不是无限大,事实上它非常小,一般设置在3~5MB左右。LOG_BUFFER有一定的触发条件,当满足触发条件后,会有相应进程将LOG_BUFFER中的内容写入一个特定类型的文件,就是传说中的联机重做日志文件。

16.1.4.1 联机重做日志文件(Online Redolog Files)

在Oracle数据库环境中,如果开展"评选劳动模范"之类的活动,联机重做日志绝对是当之无愧的劳模代表(没有之一)。在某些比较极端的环境,甚至自联机重做日志文件降临到Oracle数据库环境的那刻起,它就要从早忙到晚,从这头忙到那一头,再从那头忙回到这一头,艰苦朴素、吃苦耐劳,时刻履行着作为一名重做日志组成员的光荣使命,数十年如一日,毫无怨言并且无条件地服从组织安排,全心全意完成组织交待的各项任务,忠实做好各项操作的记录工作。这一切,都是每一名重做日志组成员的真实写照。

一个好汉三个帮,重做日志文件也有多个帮手,每个数据库至少要有两个重做日志文件组(一般应该为3~5组)。

联机重做日志文件是循环使用,如图16-1所示,创建了3个重做日志文件组,Oracle以循环方式使用这些重做日志文件组。如当前在写LOG日志组1,那么LOG日志组1即为CURRENT状态,当该重做日志文件组中的日志文件被写满数据后,后台进程LGWR就开始写下一个,即LOG日志组2(此时LOG日志组1状态被切换为ACTIVE状态,LOG日志组2的状态则变为CURRENT)。以此类推,当所有的日志文件都被写满后,后台进程LGWR再次重新写入LOG日志组1……

因为联机重做日志文件非常重要,Oracle建议每组联机重做日志文件至少要有一份冗余。Oracle管这种方式叫复合(Multiplexed),即为每个重做日志文件保持多份镜像,这样一旦因为磁盘损坏,或误操作导致丢失了某个重做日志文件,只要该组至少还有一个重做日志文件状态正常,就能够保证数据不会丢失。

1.管理联机重做日志

创建联机重做日志文件时都是以组为单位,也就是说,想为数据库添加一个联机重做日志文件,就必须先为数据库创建一个联机重做日志文件组(如果使用DBCA建库,默认会创建三个联机重做日志文件组)。创建联机重做日志文件组的语法如图16-2所示。

在创建重做日志文件组时,可以为联机重做日志文件指定复合,并设置联机重做日志文件的大小,例如:

1.JSSBOOK> ALTER DATABASE ADD LOGFILE GROUP 4

2. 2 ('f:\oracle\oradata\jssbook\redod01.log',

3. 3 'f:\oracle\oradata\jssbook\redod02.log') size 50m;

4.Database altered.

删除连接联机重做日志文件组的语法就更简单了,例如,删除刚创建的GROUP 4:

1.JSSBOOK> ALTER DATABASE DROP LOGFILE GROUP 4;

2.Database altered.

注意

使用ALTER DATABASE DROP LOGFILE命令删除联机重做日志文件组时,不能删除当前系统正在使用(CURRENT)或活动(ACTIVE)状态的联机重做日志文件组(一般来说,刚刚创建的联机重做日志文件组的状态应该为UNUSED,表示还从未被写入过数据)。另外,ALTER DATABASE DROP LOGFILE命令只删除该联机重做日志文件组在数据字典中的定义,不会级联删除操作系统中对应的物理文件,如果需要删除对应的物理文件,DBA必须手动通过操作系统命令进行删除。

你也可以为当前的联机重做日志组添加联机重做日志文件,语法如图16-3所示。

例如,为第3组联机重做日志添加日志文件:

1.JSSBOOK> ALTER DATABASE ADD LOGFILE MEMBER 'f:\oracle

2.\oradata\jssbook\redoa02.log' TO GROUP 1;

3.Database altered.

注意

添加联机重做日志文件不能指定大小,因为每个联机重做日志文件组中的文件都是相互冗余,因此文件大小必须一致。实际上在Oracle数据库中,每一个联机重做日志文件组都可以拥有不同于其他联机重做日志文件组的大小,不过Oracle建议数据库中每组联机重做日志文件都拥有相同的大小。

删除联机重做日志文件组中的某个日志文件也很简单,如删除GROUP1中刚刚添加的日志文件,执行命令如下:

1.JSSBOOK> ALTER DATABASE DROP LOGFILE MEMBER '

2.f:\oracle\oradata\jssbook\redoa02.log';

3.Database altered.

注意

删除联机重做日志文件组成员前,必须确保删除后该联机重做日志文件组中至少还拥有一个组员,不然删除操作可能会触发ORA-00361错误。

2.查看联机重做日志

有两个视图可以用来查询当前系统中的联机重做日志文件的相关信息,其中用V$LOG视图查询当前的联机重做日志文件组信息,例如:

1.JSSBOOK> SELECT * FROM V$LOG;

2.GROUP# THREAD#SEQUENCE# BYTES MEMBERS ARCSTATUS FIRST_CHANGE#F

IRST_TIM

3.---------------------------------------------- ---------------------

4. 1 1 13 524288002YESINACTIVE 865158536029-JUN-09

5. 2 1 14 52428800 1NO CURRENT 865162651401-JUL-09

6. 3 1 12 524288001YESINACTIVE 8651585358 29-JUN-09

注意该视图中的STATUS列,表示对应的联机重做日志文件组状态,可能有下列几个值:

UNUSED:表示该联机重做日志文件组对应的文件还从未被写入过数据,通常刚刚创建的联机重做日志文件组会显示成这一状态。

CURRENT:当前Oracle数据库正在使用的联机重做日志文件组。

ACTIVE:如果处于这一状态,表示虽然当前并未使用,不过该文件中内容尚未归档,或者文件中的数据没有全部写入数据文件,一旦需要实例恢复,必须借助该文件中保存的内容。

CLEARING:表示该组重做日志文件正被重建(重建后该状态会变成UNUSED)。

CLEARING_CURRENT:表示该组重做日志重建时出现错误。

INACTIVE:表示对应的联机重做日志文件中的内容已被妥善处理,该组联机重做日志当前处于空闲状态。

V$LOGFILE则可以查询当前的联机重做日志文件明细,例如:

1.JSSBOOK> SELECT * FROM V$LOGFILE;

2.GROUP#STATUS TYPE MEMBER

3.IS_

4.------------------------ ---------------------------------------------

--------

5. 1 ONLINE F:\ORACLE\ORADATA\JSSBOOK\REDO01.LOG

6.NO

7. 2 ONLINE F:\ORACLE\ORADATA\JSSBOOK\REDO02.LOG

8.NO

9. 3 ONLINE F:\ORACLE\ORADATA\JSSBOOK\REDO03.LOG

10.NO

11.1INVALID ONLINE F:\ORACLE\ORADATA\JSSBOOK\REDOA02.LOG

12.NO

该视图中GROUP#列关联V$LOG.GROUP#,而MEMBER列则显示日志文件存储的实际路径。另一个需要注意的是TYPE列,该列只有两个值:STANDBY表示该日志文件为Standby数据库专用,即Standby Redologs,ONLINE 则表示该日志文件为普通联机重做日志文件。

3.设置联机重做日志文件大小

很多朋友可能会有疑问,究竟为联机重做日志文件分配多大的空间合适呢?这确实是一个很值得讨论的话题,不过这一问题并没有准确或者说固定的答案,每个Oracle数据库设置的值可能都不相同。如果愿意深入研究的话,那么我认为在创建联机重做日志文件时,至少有下面几个因素需要考虑到:

数据修改频繁度。联机重做日志文件不能设置得太小。如数据修改比较频繁,"可能"会产生大量的重做信息(并不是所有操作都会产生重做日志,后面将会专门谈到这一点,因此这里用可能两个字),这样重做日志文件就必然会被频繁地读写,一组写满了换另一组,另一组也写满再接着切换下一组。

如果数据的修改量非常大,而联机重做日志文件又设置得较小,那么从数据库状态来看,就会表现成日志文件在频繁地执行切换操作,不过,一旦日志文件切换时发现下一组重做日志文件尚未完成写入,那么数据库就不得不停顿,等待该组重做日志文件完成归档或数据写入,此时Oracle实例将不得不暂时停止,相

当于进入了假死状态,直到出现可用的重做日志文件组为止。因此如果数据库的修改比较频繁,那么联机重做日志文件就不能设置得太小。

平均恢复时间。联机重做日志文件不能设置得太大。数据在被修改时并非直接写入数据文件,而是写入重做日志文件,当触发检查点(CKPT)操作时会从重做日志中读取已提交的数据并写入数据文件,而触发重做日志文件中数据写向数据文件的条件之一,就是日志文件切换。在没有其他条件触发检查点的情况下,只有等重做日志文件切换时,才会将修改的数据真正保存到数据文件中。如果联机重做日志文件设置得较大,那么这一过程也会被相应延长,在一般情况下当然无所谓,不过如果考虑到万一遇到数据库崩溃,需要进行实例恢复的话,Oracle在执行实例恢复时也必须花费相应长的时间来处理这个巨大的日志文件(实际上没有这么糟糕,自8i后Oracle引入了增量检查点的特性,数据也是在持续不断地写入数据文件的)。因此考虑到Oracle实例快速从崩溃中恢复的因素,重做日志文件不宜设置过大。

高峰时的负载。每一个数据库系统都会根据具体应用的业务,而表现出不同的负载状态,某些系统可能早晨8:00~10:00点最为繁忙,有些系统则是凌晨1:00~3:00点比较繁忙,其他时段则相对比较空闲;不管是什么类型的数据库系统,在设置联机重做日志文件大小时,都应该以最繁忙时段时产生的重做日志量为准。如某个数据库系统每天产生50GB的日志,但是其中40GB是在13:00~15:00之间产生,那么在设置重做日志文件大小时,就应该调整到足够放得下这期间生成的日志的大小,而不能按照平均每小时2GB左右的日志来确定。按照一般Oracle数据库系统以10~15分钟左右的时间切换一次的频率(建议频率,并非必选频率),此处可以设置单个重做日志文件为3GB左右大小。

4.重做日志的生成

并不是所有的操作都会被记录重做日志。在执行某些操作时,DBA可能会希望尽可能少的记录重做日志,以加快执行速度,如执行某些DDL语句时附加NOLOGGING子句或执行DML时指定HINT APPEND的方式操作数据,这种操作方式不会产生重做记录(或者是只生成了极少一部分),另外像SQL*Loader这类的工具采用直接路径方式时由于跳过了SQL引擎,也不会生成重做记录。

不过如果你想,可以让所有操作均记录重做日志,Oracle数据库有一个Force Logging的属性,一旦将数据库改为Force Logging,则Nologging和Append Hint方式自动失效(甚至连SQLLDR命令的直接路径导入也会自动转换为常规路径),在这种方式下可以确保数据库中所做的操作均会记录重做信息。

查询当前数据库是否启用了Force Logging,可以查询V$DATABASE视图的Force_Logging列,例如:

1.JSSBOOK> SELECT FORCE_LOGGING FROM V$DATABASE;

2.FOR

3.---

4.NO

在默认情况下数据库处于Noforce Logging状态,要将数据库置于Force Logging模式,执行下列语句即可:

1.JSSBOOK> ALTER DATABASE FORCE LOGGING;

2.Database altered.

该设置即时修改即时生效。不过需要注意的是,如果执行该操作时,数据库正在执行一些类似Nologging 的操作,那么Force Logging必须等待这些操作完成后,才能对数据库属性进行修改。

取消Force Logging模式也很简单,执行下列语句即可:

相关主题
相关文档 最新文档