一.REDO
重做日志文件(redo log file)对oracle数据库来说至关重要。它们是数据库的事务日志。oracle维护着两类重做日志文件:在线(online)重做日志文件和归档(archived)重做日志文件。这两类重做日志文件都用于恢复;其主要目的是,万一实例失败或介质失败。它们就能派上用场。
如果数据库所在主机掉电,导致实例失败,Oracle会使用在线重做日志将系统恰好恢复到掉电之前的那个提交点。如果磁盘驱动器出现故障(这是一个介质失败),oracle会使用归档重做日志以及在线重做日志将该驱动器上的数据备份恢复到适当的时间点。另外,如果你"不小心"截断了一个表或者删除了某些重要的信息,然后提交了这个操作,那么可以恢复受影响数据的一个备份,并使用在线和归档重做日志文件把它恢复到这个“意外发生前的时间点”。
归档重做日志文件实际上就是已填满的“旧”在线重做日志文件的一个副本。系统将日志文件填满时,ARCH进程会在另一个位置建立在线重做日志文件的一个副本,也可以在本地和远程位置上建立多个另外的副本。如果由于磁盘驱动器损坏或者其他物理故障而导致失败,就会用着些归档重做日志文件执行介质恢复。oracle拿到这些归档重做日志文件,并把它们应用于数据文件的备份,使这些数据文件能“赶上”数据库的其余部分。归档重做日志文件数数据库的事务历史。
每个Oracle数据库都知识有两个在线重做日志组,每个组至少有一个成员(重做日志文件)。这些在线重做日志组以循环方式使用。Oracle会先写组1中的日志文件,等写到1组中文件的最后时刻将切换到日志文件组2,开始写这个组的文件。等到把日志文件组2写满时,会再次切换回日志文件组1.
数据库之所以成为数据库(而不是文件系统),是因为它有自己独有的一些特征,重做日志或事务日志就是其中重要的特性之一。重做日志可能是数据库中最重要的恢复结构,不过,如果没有其他部分(如undo段,分布式事务恢复等),单靠重做日志什么也做不了。重做日志是数据库区别于传统文件系统一个主要的因素。oracle正写到一半的时候可能发生掉电,利用在线重做日志,我们就能有效地从这个掉电失败中恢复。归档重做日志则允许我们从家中失败中恢复,如硬盘损坏,或者由于人为错误而导致数据库丢失。如果没有重做日志,数据库提供的保护比文件系统多不了多少。
二.UNDO
从概念上将,UNDO正好与redo相对。你对数据执行修改时,数据会生成undo信息。以便回到更改以前的状态。这样万一你执行的事务或语句由于某种原因失败了,或者如果你用一条rollback语句请求回滚,就可以利用这些undo信息将数据放回修改前的样子。redo用于失败时重放事务(既恢复事务),undo则用于取消一条语句或一组语句的作用。与redo不同,undo在数据库内部存储在一组特殊的段中,这称为UNDO段(undo segment),通常对undo有一个误解,认为undo用于将数据库物理地恢复到执行语句或者事务之前的样子,但实际上并非如此。数据库只是逻辑地恢复到原来的样子,所有修改都被逻辑地取消,但是数据结构以及数据块本身在回滚后可能大不相同。原因在于:在所有多用户系统中,可能会有数十,数百甚至数千个并发事务。数据库的主要功能之一就是协调对数据的并发访问。也许我们的事务在修改一些快,而一般来讲往往会有许多其他的事务也在修改这些块。因此,不能简单地将一个块放回到我们事务前的样子,这样会撤销其他人(其他事务)的工作。
通过下面的例子可以看到undo generation具体情况:
(1)创建一个空表:
(2)对它做一个全表扫描,观察读表所执行的I/O数量。
(3)在表中填入许多行(但没有提交)
(4)回滚这个工作,并撤销。
SQL> create table t as select * from all_objects where 1=0;
Table created.
SQL> select * from t;
no rows selected
SQL> set autotrace traceonly statistics;
SQL> select * from t;
no rows selected
Statistics
----------------------------------------------------------
0 recursive calls
0 db block gets
3 consistent gets
0 physical reads
0 redo size
1343 bytes sent via SQL*Net to client
513 bytes received via SQL*Net from client
1 SQL*Net roundtrips to/from client
0 sorts (memory)
0 sorts (disk)
0 rows processed
SQL> insert into t select * from all_objects;
85295 rows created.
SQL> rollback;
Rollback complete.
SQL> select * from t;
no rows selected
Statistics
----------------------------------------------------------
0 recursive calls
0 db block gets
1218 consistent gets
0 physical reads
0 redo size
1343 bytes sent via SQL*Net to client
513 bytes received via SQL*Net from client
1 SQL*Net roundtrips to/from client
0 sorts (memory)
0 sorts (disk)
0 rows processed
前面的INSERT导致将一些块增加到表的高水位线(HWM)之下,这些块没有因为回滚而消失,它们还在那里,而且还在那里,而且已经格式化,只不过现在为空。全表扫描必须读取这些块,看其中是否包含这些行。