天天看点

Oracle之不完全恢复

整理自《Oracle database 11g RMAN 备份与恢复》

001 概述

    顾名思义,不完全恢复就是指不完全的数据库恢复。不完全恢复与完全恢复在许多方面是相同的,它们基本的命令集相同,但不完全恢复添加了一些其它命令。引起不完全恢复的原因有很多,如丢失了联机重做日志或归档的重做日志,或者出现重大的用户错误。<b>不完全恢复会影响整个数据库</b>;换句话说,不能只对数据库的一部分执行不完全恢复操作,因为这会使数据库的一部分具有与这个数据库其余部分不同的系统更改号(SCN)或时间点。

    不完全恢复影响的是整个数据库,这一点是非常重要的概念。一个典型的例子是:用户错误地删除了表空间中的一个表,并且没有备份这个表。要求将这个表空间恢复发哦该用户执行删除操作之前的时间点。

    初级DBA起初可能会认为只需要还原损坏表空间的数据文件并将这些数据文件恢复到执行删除操作之前的时间点。这些操作看上去非常符合逻辑,实际上,这正是逻辑备份的操作。因此,初级DBA还原了数据文件,并将表空间恢复到删除操作之前的时间点,但当其尝试打开数据库时,RMAN会给出下面的信息:

ERROR at line 1:

ORA-01113:file 3 needs media revoery

ORA-01110:data file 3:'/u01/app/oracle/oradata/ORCL/INDEX01.DBF'

    在这个示例中,Oracle告诉用户恢复数据文件是成功的,但是这些数据文件恢复得不够,与数据库的其他部分不一致!因此,不完全恢复并非所有灾难的解决方案,它只是某些灾难的解决方案。如果需要某种形式的不一致恢复(将一些数据库数据还原至与数据库剩余部分不同的时间点),则有表空间时间点恢复,或者闪回技术。

    然而,如果需要将整个数据库还原到闪回数据库无法到达的过去的某个时间点,则需要使用不完全恢复。当执行数据库不完全恢复时,需要使用Resetlogs命令,因为差不多所有的不完全恢复情况都要用到Resetlogs命令。

    我们将在下面介绍该命令,随后还要讨论实际的不完全恢复方法,这些方法包括基于时间、SCN、日志序列或取消的恢复。

002 使用Resetlogs命令

    在不完全恢复期间,通常需要使用Resetlogs命令打开数据库,这是因为我们要从已经建立的现有重做流中脱离出来,并且需要向Oracle说明这种情况。Resetlogs命令表示一个数据库逻辑生存周期的结束和另一个数据库逻辑生存周期的开始。数据库的逻辑生存期也称为一个对应物(incarnation)。每次使用Resetlogs命令都会创建一个新的数据库对应物,这对于恢复操作来说非常重要,我们将在后面讨论这个问题。

    每次使用Resetlogs命令时,SCN计数器不会被重置,不过Oracle会重置其它计数器(如日志序列号),同时还会重置联机重做日志的内容(如果有必要还可以重新创建联机重做日志)。

    从Oracle database 10g开始,简化了通过Resetlogs命令进行的恢复。在归档的重做日志名中添加了一个新的替换字符串(%r),该字符串表示Resetlogs ID号。在log_archive_dest_format参数字符串中包括%r时,归档的重做日志名在每个Resetlogs命令中保持唯一。这种改动以及其他的内部Oracle数据库改动使Oracle可以很容易地通过给定的Resetlogs操作恢复数据库。因此,可以很容易地在执行Resetlogs操作后立刻备份数据库。然而,我们仍然认为在任何不完全恢复后备份数据库是很好的想法。

    注意:在以前版本的RMAN中,需要重新创建所有的临时表空间临时文件。Oracle database 10g和以后的版本中则不需要这种操作,RMAN在恢复数据库过程期间会创建这些数据文件,甚至在不完全恢复期间也是如此!

003 创建恢复点

    使用RMAN执行不完全恢复操作时需要完成的一个工作是创建恢复目标。<b>恢复目标是恢复进程的终点,通常我们基于一个时间点、一个指定的SCN或一个日志序列号来标识它。</b>我们可以使用许多不同的方法创建恢复目标。首先,可以在run代码块中使用set命令与until time、until SCN或until sequence参数,下面的示例使用set until time命令创建了一个为2016年1月19日下午3点的恢复目标:

    run

    {

    set until time "to_date('01/19/16 15:00:00','mm/dd/yy hh24:mi:ss')";

    restore database;

    recover database;

    alter database open resetlogs;

    }

    执行这条命令时,RMAN会查找与恢复目标时间最近(并非恢复目标时间本身,也不能是恢复目标之后的时间)的备份集,并且从这个备份集中还原数据库。如果数据库置于noarchivelog模式中,恢复操作会在备份集的时间点停止;否则在执行recover命令期间,Oracle会在所定义的恢复目标(不包含恢复目标本身)上应用归档的重做日志(以及需要应用的任何增量备份)。

    注意:如果尝试恢复到特定备份的完成点,则必须恢复到备份集中文件的ckp SCN或ckp time,在不同备份集的RMAN的list命令中列出了这些内容(例如 list backup)。有时候使用备份的ckp time并不够,还可能导致ORA-1152错误。

    也可以选择在restore和recover命令中直接使用until time、until SCN或until sequence命令,这样就避免使用run代码块(我们倾向于使用这种方法)。下面是在还原和恢复数据库时所使用的until time命令示例:

    --we assume that your control file is intact

    startup mount;

    restore database until time

    “to_date('01/19/16 13:00:00','MM/DD/YY HH24:MI:SS')";

    recover database until time

    "to_date('01/19/16 13:00:00','MM/DD/YY HH24:MI:SS')";

004 基于时间的恢复

    003中给出了一些基于时间的恢复示例。这种恢复类型允许用户将数据库恢复到与指定时间一致的状态。当然,如果不存在能将数据库还原到用户请求的时间的有效备份或归档重做日志,Oracle就会生成如下所示的错误:

Oracle之不完全恢复

    最后需要强调的是必须具备在我们所指定的恢复时间之前生成的数据库备份,此外还需要所有的归档重做日志。利用list和report命令,我们可以确定RMAN还原数据库可以使用的备份。

005 基于SCN的恢复

    Oracle允许用户将数据库恢复到指定的SCN。实际上,这并不是一种常用的恢复方法,不过最好了解一下它的用法。下面是一个将数据库还原到指定SCN的示例:

    假定控制文件完整:

    startup mount;

    restore database until SCN 10000;

    recover database until SCN 10000;

    在这个示例中,我们将数据库还原到SCN 10000(但是不包含这个SCN)。

006 基于日志序列的恢复

    RMAN允许用户将数据库恢复到指定序列号的归档重做日志。如果归档的重做日志中存在间隙,使用这种恢复方法就非常方便。间隙通常意味着我们只能将数据库还原到间隙的开始点。下面是一个在RMAN中执行基于日志序列的恢复操作的示例:

    假定控制文件是完整的:

    restore database until sequence 100 thread 1;

    recover database until sequence 100 thread 1;

    在这个示例中,我们将数据库还原到日志序列为100(但是不包含这个日志序列)的数据库。

007 基于删除的恢复

    RMAN不支持类似于sqlplus所做的基于删除的恢复(虽然基于删除的恢复在一定程度上非常类似于基于日志序列的恢复),而是希望用户了解恢复到的时间、SCN或日志序列号,因为这样非常有意义。如果需要执行基于删除的恢复,则需要从RMAN中将数据文件还原到恢复时间之前的一些时间点。我们需要手动析取基于删除的恢复所需的归档重做日志,然后需要从sqlplus客户端中执行数据库的基于删除的恢复。

008 使用还原点恢复

    可以利用还原点定义数据库还原到的时间点。基于还原点还原数据库,只包含restore和recover命令的to restore point子句,如下所示:

    restore database until restore point tango_one;

    recover database until restore point tango_one;

    也可以使用run代码块和set until restore point命令创建还原点,如下所示:

    run {

    set restore point tango_one;

    restore databsae tango_one;

    recover database tango_one;