Redo和undo是Oracle最重要的两部分数据。
Redo(重做信息)是Oracle在线(Online)或归档(Arichived)重做日志文件中记录的信息,可以用于Redo重放事务信息。
Undo(撤销信息)是Oracle在undo段中记录的信息,用于撤销或回滚事务。
REDO(用于前滚数据)
Redo也就是重做日志文件(Redo log file),Oracle维护着两类重做日志文件:在线(Online)重做日志文件和归档(Archived)重做日志文件。这两类重做日志文件都用于恢复,其主要目的是万一实例失败或者介质失败,它们能够恢复数据。
Undo(用于回滚数据)
当用户对数据库进行修改时,数据库会生成Undo信息,以便回滚到更改前的状态。Undo在数据库内存放在一组特殊的段中(回滚段 rollback segment),利用undo,数据库只是逻辑的恢复到原来的样子,所有修改都逻辑的取消,但是数据结构以及数据块本身在回滚后可能不大相同。
undo生成对于直接路径操作(/*+ append*/)不适用,直接路径操作能够绕过表上的undo生成。
Undo和Redo的协作
尽管Undo存储在Undo表空间中,但也会受到redo保护,会把undo信息当成表数据或索引数据一样,对undo的修改会生成一些redo,将记入重做日志,将undo数据增加到undo段中,并像其他部分的数据一样,在缓冲区缓存中得到缓存。
以一个例子来说明一下(一个事务包含一组sql语句):
insert into t(x,y) values(1,1);
update t set x = x+1 where x = 1;
delete from t where x = 2;
Insert
对于第一条INSERT INTO T语句,redo和undo都会生成。所生成的undo信息足以使INSERT“消失“。INSERT INTO T生成的redo信息则足以让这个插入”再次发生“。
这里缓存了一些已修改的undo块、索引块和表数据块。这些块得到重做日志缓冲区中相应条目的“保护“。
Update
UPDATE所带来的工作与INSERT大体一样。不过UPDATE生成的undo量更大;由于存在更新,所以需要保存一些“前“映像。系统状态如下图所示。
块缓冲区缓存中会有更多新的undo段块。为了撤销这个更新,如果必要,已修改的数据库表和索引块也会放在缓存中。我们还生成了更多的重做日志缓存区条目。下面假设前面的插入语句生成了一些重做日志,其中有些重做日志已经刷新输出到磁盘上,有些还放在缓存中。
Delete
DELETE会生成undo,块将被修改,并把redo发送到重做日志缓冲区。这与前面没有太大的不同,实际上,它与UPDATE如此类似.
Commit
在此,Oracle会把重做日志缓冲区刷新输出到磁盘,系统状态如下图所示。
假设目前已修改的块放在缓冲区缓存中;有一些块已经刷新输出到磁盘上,有一些还没有。但是如果重做这个事务所需的全部redo都安全地存放在磁盘上,那么修改就是永久的了,即使有一些修改的块还没有刷新输出到磁盘上。(commit并不是把所有的修改持久化到了数据文件,而是所有的redo文件持久化到磁盘文件,只要所有的重做日志文件持久化到磁盘,这些修改就是永久的了。)如果从数据文件直接读取数据,可能会看到块还是事务发生前的样子,因为很有可能DBWR还没有(从缓冲区缓存)写出这些块。这没有关系,如果出现失败,可以利用重做日志文件来得到最新的块。