1、概念

    REDO LOG是Oracle为确保已经提交的事务不会丢失而建立的一个机制。实际上REDO LOG的存在是为两种场景准备的:

  • 实例恢复(INSTANCE RECOVERY);

  • 介质恢复(MEDIA RECOVERY)。

    实例恢复的目的是在数据库发生故障时,确保BUFFER CACHE中的数据不会丢失,不会造成数据库的不一致;

介质恢复的目的是当数据文件发生故障时,能够恢复数据。

虽然这两种恢复使用的机制类似的,但是这两种恢复也有着十分本质的不同,这一点也是很多DBA经常会混淆的。

REDO LOG的数据是按照THREAD来组织的,对于单实例系统来说,只有一个THREAD,对于RAC系统来说,可能存在多个THREAD,每个数据库实例拥有一组独立的REDO LOG文件,拥有独立的LOG BUFFER,某个实例的变化会被独立的记录到一个THREAD的REDO LOG文件中。

2、恢复步骤

    对于介质恢复和实例恢复来说,第一个步骤都是通过REDO LOG的信息进行前滚,在做前滚的时候,通过REDO LOG文件里记录的数据库变化矢量,根据SCN的比对,提交到相关的数据文件上,从而使数据文件的状态向前滚动。大家要注意的是,UNDO表空间的变化也被记录到REDO LOG里了,因此UNDO表空间相关的数据文件也会被前滚。当前滚到最后一个可用的REDO LOG或者归档日志的时候,所有的数据库恢复层面的工作就全部完成了。这个时候,数据库包含了所有的被记录的变化,这些变化中有些是已经提交,有些是尚未提交的。在最新状态的UNDO表空间中,我们也可以看到一些尚未提交的事务。

因此数据库下一步需要做的事情是事务层面的处理,回滚那些尚未提交的事务,以确保数据库的一致性。

    对于单实例的系统,实例恢复一般是在数据库实例异常故障后数据库重启时进行,当数据库执行了SHUTDOWN ABORT或者由于操作系统、主机等原因宕机重启后,在ALTER DATABASE OPEN的时候,就会自动做实例恢复。而在RAC环境中,如果某个实例宕了,活着的实例将会接管,替宕掉的实例做实例恢复。除非是所有的实例都宕了,这样的话,第一个执行ALTER DATABASE OPEN的实例将会做实例恢复。这也是REDO LOG是实例私有的组件,但是REDO LOG文件必须存放在共享存储上的原因。

    Oracle数据库的CACHE机制是以性能为导向的,CACHE机制应该最大限度的提高数据库的性能,因此CACHE被写入数据文件总是尽可能的推迟。这种机制大大提高了数据库的性能,但是当实例出现故障时,可能出现一些问题。

首先是在实例故障时,可能某些事物对数据文件的修改并没有完全写入磁盘,可能磁盘文件中丢失了某些已经提交事务对数据文件的修改信息。其次是可能某些还没有提交的事务对数据文件的修改已经被写入磁盘文件了。也有可能某个原子变更的部分数据已经被写入文件,而部分数据还没有被写入磁盘文件。实例恢复就是要通过ONLINE REDO LOG文件中记录的信息,自动的完成上述数据的修复工作。这个过程是完全自动的,不需要人工干预。

在这个机制里,有两个问题需要解决:

第一个是如何确保已经提交的事务不会丢失;

第二个是如何在数据库性能和实例恢复所需要的时间上做出平衡,既确保数据库性能不会下降,又保证实例恢复的快速。

    解决第一个问题比较简单,Oracle有一个机制,叫做Log-Force-at-Commit,就是说,在事务提交的时候,和这个事务相关的REDO LOG数据,包括COMMIT记录,都必须从LOG BUFFER中写入REDO LOG文件,此时事务提交成功的信号才能发送给用户进程。通过这个机制,可以确保哪怕这个已经提交的事务中的部分BUFFER CACHE还没有被写入数据文件,就发生了实例故障,在做实例恢复的时候,也可以通过REDO LOG的信息,将不一致的数据前滚。

    解决第二个问题,oracle是通过checkpoint机制来实现的。Oracle数据库中,对BUFFER CAHCE的修改操作是前台进程完成的,但是前台进程只负责将数据块从数据文件中读到BUFFER CACHE中,不负责BUFFER CACHE写入数据文件。BUFFER CACHE写入数据文件的操作是由后台进程DBWR来完成的。DBWR可以根据系统的负载情况以及数据块是否被其他进程使用来将一部分数据块回写到数据文件中。这种机制下,某个数据块被写回文件的时间可能具有一定的随机性的,有些先修改的数据块可能比较晚才被写入数据文件。而CHECKPOINT机制就是对这个机制的一个有效的补充,CHECKPOINT发生的时候,CKPT进程会要求DBWR进程将某个SCN以前的所有被修改的块都被写回数据文件。这样一旦这次CHECKPOINT完成后,这个SCN前的所有数据变更都已经存盘,如果之后发生了实例故障,那么做实例恢复的时候,只需要冲这次CHECKPOINT已经完成后的变化量开始就行了,CHECKPOINT之前的变化就不需要再去考虑了。

到目前为止,我们了解了实例恢复机制的一些基本的原理,我们也可以大体上理解REDO LOG的工作机制了。不过我想我们还需要再更加深入一些。了解一些更为深入的内幕。实际上通过上面的介绍,大家也许已经觉得对实例恢复了解的很透彻了,而实际上,有很多问题我们还没有解决。有些爱动脑筋的读者可能要问了,有没有可能数据文件中的变化已经写盘,但是REDO LOG信息还在LOG BUFFER中,没有写入REDO LOG呢,这种情况如何恢复呢?

    这里我们又要引入一个名词:Write-Ahead-Log,就是日志写入优先。日志写入优先包含两方面的算法:

    第一个方面是,当某个BUFFER CACHE的修改的变化矢量还没有写入REDO LOG文件之前,这个修改后的BUFFER CACHE的数据不允许被写入数据文件,这样就确保了再数据文件中不可能包含未在REDO LOG文件中记录的变化;

    第二个方面是,当对某个数据的UNDO信息的变化矢量没有被写入REDO LOG之前,这个BUFFER CACHE的修改不能被写入数据文件。

3、区别

    介质恢复和实例恢复的机制是类似的,所不同的是,介质恢复是当存储的数据文件出现故障的时候进行的,介质恢复无法自动进行,必须手工执行recover Database或者recover datafile命令来实施。一般来说,介质恢复是从一个恢复的数据文件为起点进行恢复,因此在做介质恢复的时候,需要使用归档日志。