Oracle恢复内部原理 2
2010年06月13日 星期日 12:42
4.3 END BACKUP 当发出END BACKUP命令时,各热备的表空间的数据文件将发生下列操作: 1.还原了数据文件的联机模糊标志位。 2.在重做日志中写入一笔该数据文件结束热备份的重做记录。这笔重做记录只会在介质恢复中有用,记录了热备份开始时刻的SCN(该SCN跟数据文件头部被冻结的检查点的SCN一致)。这笔记录也标志着热备份期间的重做日志的结束。介质恢复时读到这个热备份结束标记,就知道热备份期间产生的重做日志都被应用到了数据文件上。然后介质恢复就清除热备份模糊标志位。这个标志位能防止不完全恢复错误的选择在BEGIN BACKUP和END BACKUP时间点之间停止。如果一个不完全恢复在这样的点停止了,可能会导致数据文件不一致,因为备份时的复制过程可能已经包含了这个时间点之后的变更。在8.1将会见到,当数据文件的热备份标志位还在时,以重置日志的方式打开数据库将会失败。 3.清除热备份模糊标志位。 4.停止数据块前镜像记录。 5.推进数据文件的检查点到当前数据库检查点。这弥补了热备份期间线程检查点推进了数据库检查点却无法推进数据文件头检查点(因为被冻结了)。 4.4 “崩溃”的热备份 当有数据文件处于热备份状态时,正常关闭启动了热备份的实例或者最后一个实例都不被允许,还有将热备的数据文件正常脱机或临时脱机也不行。这是为了保证结束热备份的标志记录能正常产生。也告诉了管理员他们忘了发出“END BACKUP”命令。 当热备份期间实例崩溃了或者以abort方式关闭时,所有热备份中文件的热备份模糊标志位还处于被设置状态,文件头检查点还处于被冻结状态,仍旧是热备份开始时刻的检查点。即使数据文件的数据块跟数据检查点一致,文件头看起来像刚还原的备份需要介质恢复,且跟开始热备份的检查点一致,崩溃恢复还是会失败,报需要介质恢复,因为它发现数据文件处于热备份崩溃的状态中。而这个文件起始不需要介质恢复,但是需要修正一下文件头部取消“崩溃”热备份状态。 介质恢复可以恢复和打开有数据文件处于“崩溃”热备份状态的数据库。7.2版有个更好的选择,就是用命令ALTER DATABASE DATAFILE... END BACKUP将数据文件结束热备份状态,数据文件可以从视图V$BACKUP中查看。见9.6)。之所以能这样做。紧接着这个命令后,崩溃恢复就可以打开数据库。注意ALTER TABLESPACE ... END BACKUP命令在数据库没有打开的时候是不能用的。因为数据库只有在打开的时候才能通过数据字典找到表空间对应的数据文件。 5 实例恢复 实例恢复用于恢复崩溃失败或者并行服务器环境中的实例失败,所以实例恢复既可以指崩溃恢复也可以指并行服务器环境中的实例恢复(只要有一个存活的实例就可以恢复其他一个或多个失败的实例)。 实例恢复的目标就是还原失败实例在数据缓冲区中的数据块并关闭还开着的线程。实例恢复只用联机归档日志和当前联机数据文件(不需要还原历史备份)。实例恢复一次只能恢复一个线程,它从该线程最近的线程检查点开始恢复直至线程的结束。 5.1 检测是否需要实例恢复 当Oracle内核发现一个实例死掉而对应线程在控制文件中的线程打开状态位还是开的时候会自动进行实例恢复。实例恢复在下面两种情形下自动进行: 1.崩溃失败后第一次打开数据库。 2.并行服务器个别实例(不是所有的)失败了。 在并行服务器环境中,存活的实例通过下列方法检测到一个或多个实例失败需要进行实例恢复: 1.存活实例的一个前台进程在将数据文件中的块读入数据缓冲区时检测到“Invalid block lock” 。这个多发生在另一个实例已经将该块读入数据缓冲区并用锁保护了该块‘脏数据’,然后该实例失败了。 2.存活实例的前台进程通知它的SMON进程查看失败的实例。 3.存活实例可以申请死亡实例的线程打开标志锁从而发现该实例已经死亡。 存活实例的SMON进程得到一个死亡实例的列表和错误的数据块列表。注:当实例恢复结束后,这些列表中的锁都会被清掉。 5.2 Thread-at-a-Time Redo Application 实例恢复同一时间只能处理一个线程,因此同一时间也只能恢复一个实例。在处理下一个线程之前,实例恢复会将每个线程的所有重做日志(从该线程的线程检查点开始到线程结束)应用到数据文件上。这个算法的正确性取决于同一时刻只有一个实例能修改数据缓冲中的块。在不同的实例修改同一块之间,该块会被写回磁盘。因此,实例恢复时从磁盘中读入数据缓存中块只需要某一个线程就够了,那个线程包含了该块最新的修改日志。 实例恢复总是能够只要该线程的联机日志就可以完成。崩溃恢复首先处理线程检查点最低的那个线程,按照线程检查点SCN递增的顺序进行恢复。保证了数据库检查点是由每个恢复过的线程推进的。 5.3 当前联机数据文件 检查点计数器用于校验数据文件是当前联机数据文件而不是历史备份。如果数据文件是从备份中还原出来的,则需要首先进行介质恢复。 当数据文件是从备份中还原出来的时候,即使只要联机重做日志就可以恢复,介质恢复仍然不可避免。理由是崩溃恢复在处理每个线程的时候都是应用该线程检查点以后的重做日志。崩溃恢复能够用这种重做算法是因为每个块只需要最多一个线程的重做日志。 然而,如果在还原的备份上进行恢复时,无法断定要哪些线程的重做日志。因此一次一个线程的算法在这种情况下不起作用。在备份上恢复需要将多个线程的重做合并。如把数据文件检查点后的所有重做日志,按照SCN递增的顺序合并各个线程中的重做日志。这种线程合并重做算法只有介质恢复才会用(见第6节)。 崩溃恢复如果使用线程合并重做算法恢复一个备份,即使数据文件的检查点跟数据库检查点一致,依然会失败。原因是在所有的线程中,崩溃恢复会丢失数据库检查点和最高的检查点之间的重做日志。相比之下,介质恢复会从数据文件检查点开始应用重做程序。而且,即使崩溃恢复也从数据文件检查点开始应用重做程序,还是会失败。因为它只会去找联机重做日志。而所有线程可能都已经将其重做日志归档了并重用了联机日志。 如果使用了命令STARTUP RECOVER ,崩溃恢复会因为数据文件需要介质恢复而失败。此时在数据库打开之前会自动调用RECOVER DATABASE进行介质恢复。 5.4 检查点 实例恢复不会尝试应用数据文件检查点之前的重做日志(数据文件头部的检查点SCN不能决定是否需要实例恢复)。 实例恢复读取从数据文件检查点之后到线程结束之际的重做日志,找到该线程分配的最大的SCN。用于关闭线程和推进线程检查点。实例恢复结束后也会推进数据文件检查点和检查点计数器。 5.5 崩溃恢复完成 崩溃恢复完成时,所有数据文件的联机模糊位,热备份模糊位,介质恢复模糊位都将被清除掉,然后在重做日志中写入一笔特殊的重做记录,标记崩溃恢复的结束。这条记录用于通知介质恢复在恢复时何时可以清除数据文件的联机模糊位和热备份模糊位。 6 介质恢复 介质恢复用在丢失或损坏数据文件或者丢失了控制文件的情形。介质恢复将还原的数据文件恢复成当前数据文件。还能够恢复数据文件异常脱机时没有来得及做检查点操作丢失的变更。介质恢复使用归档日志和联机日志。跟实例恢复不同的是,介质恢复必须由命令显式调用。 6.1 什么时候做介质恢复 由5.3节知道,数据文件如果是还原的备份,在打开前都要进行介质恢复,即使是应用联机日志就可以恢复的。另外一种情形就是数据文件异常脱机没有做检查点操作。不做介质恢复数据库是无法打开的,需要介质恢复的数据文件也不能联机。数据库没有被任何实例打开的时候,介质恢复只能在脱机的数据文件上恢复。即使有崩溃恢复的时候也要在打开数据库显示调用介质恢复命令。此时崩溃恢复可能没有什么做的但还是会自动运行。有时候介质恢复可能发现没有日志要应用,就会报个错“不需要介质恢复”,即该文件不需要恢复。 如果当前控制文件丢失了,将一个备份控制文件还原了,介质恢复就必须做了,这是所有数据文件都联机的时候还要介质恢复的一个例子。 6.2 线程合并重做程序 介质恢复应用重做日志时用的是线程合并的重做算法。即它要同时应用所有线程的重做日志,按SCN递增的顺序合并重做日志。在还原的数据文件上应用介质恢复的过程跟在联机数据文件上应用崩溃恢复的过程的不同在于:崩溃恢复同一时刻只会应用来自一个线程的日志,因为同一时刻数据文件上的块只需要最多一个线程的重做日志(同一时刻只有一个实例可能修改该块)。在还原的备份上,则无法猜测跟该块有关的线程数目。通常介质恢复时需要同时读取所有线程的重做日志,然后按照SCN递增的顺序合并重做日志。注意这个算法依赖于数据块的变更各个线程都是按SCN递增的顺序记录的(并行服务器环境中)。 6.3 还原备份 在数据库关闭或者数据文件脱机的情况下,可以将该数据文件的备份还原。注意决不能在数据文件还在访问的情况下还原。每次都数据文件头时都会校验数据文件头部的检查点计数和数据文件在控制文件中的检查点计数以检测是否发生这种非法操作。 6.4 介质恢复命令 介质恢复命令有三种: RECOVER DATABASE RECOVER TABLESPACE RECOVER DATAFILE 这三个命令的根本区别在于恢复的数据文件集合不同。三个命令都用同样的标准决定每个数据文件是否要做介质恢复。每个数据文件上都一个排它锁,介质恢复程序开始恢复前会先申请获得这个锁。如果得不到就触发一个错误。这可以防止两个恢复会话同时恢复同一个数据文件以及防止对一个在使用的数据文件进行介质恢复。 6.4.1 RECOVER DATABASE 这个命令用来恢复所有联机数据文件。如果所有实例都正常关闭并且也没有数据文件被还原,这个命令会触发一个“no recovery required”的错误。当有实例已经打开了数据文件时这个命令也会报错因为该实例已经持有所有的锁。 6.4.2 RECOVER TABLESPACE 这个命令用来恢复指定表空间上的所有数据文件。为了将表空间名转换成具体的数据文件名,数据库必须先打开。这意味着这个表空间及其所有数据文件在数据库打开前得先脱机才能进行介质恢复。如果该表空间的所有数据文件都不需要介质恢复时会触发一个错误说没有文件需要介质恢复。 6.4.3 RECOVER DATAFILE 这个命令用来恢复指定的数据文件,无论数据库是否打开,只要能获得该数据文件上的介质恢复锁即可。当一个实例已经打开数据库的时候,则只能在脱机的数据文件上做介质恢复。 6.5 开始介质恢复 介质恢复时开始查找介质恢复起始SCN。如所有要恢复的数据文件的文件头中最低的检查点SCN。注意:如果一个数据文件的检查点SCN落在它的脱机SCN范围内(见2.18)则会引发一个异常。此时,该数据文件的脱机结束SCN将替代文件头检查点SCN参与计算介质恢复起始SCN。 然后每个激活的线程(指在介质恢复开始SCN那一刻处于激活状态的线程,见2.10)都会分配一个缓冲区用来读取重做日志。每个文件的文件头的检查点SCN被保存下来用来确保在这个SCN以前的重做日志不需要应用。结束SCN(控制文件中记录的)也被保存下来。如果是无穷大则取最大的结束SCN用来告诉介质恢复在何处停止,超出这个SCN的重做日志不需要应用(见6.10)。介质恢复结束时,之前结束SCN为无穷大的数据文件会在该结束SCN处做一个检查点操作(而不是在介质恢复结束点)。这使得一个干净脱机或者只读的数据文件在跟它的表空间干净结束SCN处进行检查点操作。 6.6 应用重做日志,介质恢复检查点 每个在介质恢复起始SCN处激活的线程(见2.10)都打开了一个日志。如果该日志是联机状态,就会自动被打开;如果该日志是归档状态,就会提示用户输入日志名称,除非是自动恢复。所有线程中的重做日志按照产生的顺序被应用,在需要的时候还会切换线程。 有个例外就是在基于取消的不完全恢复(见6.12)或者是备份的控制文件的恢复(见6.13),按序列顺序计算出的下一个联机日志如果在磁盘上会自动被应用,否则会提示输入它的完整路径。 在日志分界点,介质恢复会执行一个检查点操作。脏数据会被写入到磁盘,数据文件头检查点推进,因此在此之前的重做日志不需要再重新应用。介质恢复的检查点还可能发生在介质恢复结束时会对介质恢复开始时一些结束SCN为无穷大的数据文件在结束SCN处做检查点操作。 6.7 介质恢复和模糊状态位 6.7.1 介质恢复模糊位 数据文件头部的介质恢复模糊位用来表示由于在进行介质恢复,该数据文件可能包含比数据文件头部检查点SCN还要晚的数据变更。介质恢复模糊位在介质恢复开始的被设置,通常来说在介质恢复对数据文件头发生一次检查点时该状态位可以被清除。当介质恢复成功结束或失败时该状态位才算永久清除。在8.1将见到,在不完全恢复后以重置日志方式打开数据库,如果还有数据文件的介质恢复模糊位被设置,将会打开失败。 6.7.2 联机模糊位 介质恢复在碰到一个崩溃恢复结束标记(或者一个立即脱机的标记:发生在数据文件还没有做检查点操作就脱机),介质恢复会在下一个介质恢复检查点清除数据文件头的联机模糊位和热备模糊位(如果被设置)。 6.7.3 热备份模糊位 在碰到一个结束热备份标记(或者一个崩溃恢复结束标记),介质恢复会在下一个介质恢复检查点操作时清除热备份模糊位。在不完全恢复后以重置日志方式打开数据库时如果有数据文件热备份模糊位或其他模糊位被设置,打开将失败。这防止了不完全恢复在热备份开始和结束中间时间点结束时还能以重做日志方式成功打开数据库。在这样的时间点结束不完全恢复将会导致数据文件处于不一致状态,因为还原的备份可能包含该结束点和热备份结束点之间的数据库变更。 6.8 线程启用 当一个实例启用一个新线程的时候会在该线程的重做日志中写入一笔线程启用记录。当介质恢复碰到这样的记录时就重新分配一个重做日志缓冲区,打开新的线程的重做日志,开始应用它的重做日志。 6.9 线程禁用 线程被禁用的时候,它的当前日志被标记为线程结束。介质恢复应用完该重做日志后,会释放它的重做日志缓冲区并停止查找该线程的重做日志。 6.10 结束介质恢复(完整的介质恢复) 每个线程的当前日志(也是最后一个)都会有个线程结束标记。完整的介质恢复(相对于不完全恢复,见6.12)都会应用重做日志直至所有线程的线程结束处。线程结束标记可以认为是没有当前控制文件,因为线程结束标记在日志头部而不是在控制文件中的记录中。 注意:备份当前联机日志并在后面还原是很危险的,很容易导致对当前线程结束的误判。因为备份中的线程结束标记相对于当前线程结束的日志而言是过期了的。 如果正在做介质恢复的数据文件在控制文件中(假定是当前控制文件)的结束SCN是无穷大,介质恢复将会联机程结束之前停止,重做程序将联机程结束点的SCN处停止,因为没有超出这个SCN的重做日志存在了。 像2.15中描述的那样,结束SCN是在数据文件脱机时被设置的。如果没有上面这个处理方式,将不能保证数据库打开的时候在结束SCN无穷大的数据文件上的介质恢复何时能停止。 6.11 自动恢复 当介质恢复命令后加上AUTOMATIC选项时将会自动进行介质恢复。它省去了让用户输入归档重做日志文件路径的麻烦,前提是它们在磁盘上。只要日志序号能确定,日志文件名就可以根据数据库初始化参数LOG_ARCHIVE_DEST和LOG_ARCHIVE_FORMAT计算出来。除非用户指定其他的归档目录,当前LOG_ARCHIVE_DEST指定的值将会被使用。介质恢复开始检查点(见6.5)中包含(RBA字段中)线程(产生该开始检查点的线程)初始的日志序号。如果启用了多个重做日志线程,将根据控制文件中的日志历史记录部分将开始SCN映射到各个线程对应的日志序列号。一旦第一个恢复用的日志找到了,后续的日志按顺序应用。如果不能确定初始的日志序号,用户就得猜测直到找到正确的日志。介质恢复开始检查点中的timestamp字段值将帮助用户决定。 6.12 不完全恢复 RECOVER DATABASE命令可以在所有重做日志被应用前停止,这种类型的恢复就是不完全恢复。不完全恢复后打开数据库必须以重置日志方式打开。 不完全恢复将数据库恢复到指定时间点或之前的数据库一致状态。所有后续的更新将丢失。 不完全恢复主要用于下列情形: a.因为有文件损坏必须进行介质恢复,但由于某个归档日志或联机日志损坏或丢失,不能进行完全恢复。 b.所有处于激活状态的联机日志都不可用,因此无法进行实例恢复,这个情形变成上一个情形。 c.为了恢复一个用户错误的操作(如删了表或者数据等),将数据库恢复到错误操作之前的一个数据库一致的点 6.12.1 Incomplete Recovery UNTIL Options 根据停止的方式分,不完全恢复有三种类型: a.基于取消的不完全恢复,命令:RECOVER DATABASE UNTIL CANCEL b.基于SCN的不完全恢复,命令:RECOVER DATABASE UNTIL CHANGE c.基于时间点的不完全恢复,命令:RECOVER DATABASE UNTIL TIME 基于取消的不完全恢复在用户输入cancel(而不是日志路径)的时候停止恢复。联机日志也不会自动被应用,防止在下一个日志开始前取消。如果多个线程要进行恢复,可能照成某些线程的重做日志只是部分应用。 基于SCN的不完全恢复停止应用指定SCN以及更高SCN相关的重做日志。因此在该SCN时提交的事务(或更晚提交)将会被回滚。如果你想恢复到某个事物提交点SCN时,将将该SCN值加一。 基于时间点的不完全恢复,跟基于SCN的不完全恢复类似,只是输入的是时间点。介质恢复根据重做日志块头部的时间来将该时间点转换成SCN,然后恢复到该SCN处停止。 6.12.2 不完全恢复和数据一致性 为了防止不完全恢复破坏数据库完整性,所有数据文件必须恢复到同一点。并且没有任何一个数据文件拥有该点之后的数据库变更。这就要求介质恢复用的数据文件必须是从早于期望恢复的时间点之前的备份中还原出来的。系统用文件头的模糊位(见8.1)来保证数据文件上没有停止时间点之后的变更。 6.12.3 不完全恢复和控制文件记录的数据文件 如果要不完全恢复到某个数据文件被删除的时间点之前,则控制文件中必须有该被删除的数据文件记录,否则无法进行恢复。而现有的控制文件已经没有该数据文件的记录了。一个可选的方法就是恢复的时候使用删除数据文件之前时间点备份的控制文件进行不完全恢复;另一个可选的方法就是用CREATE CONTROLFILE命令创建一个控制文件包含被删除的数据文件。 不完全恢复到某个数据文件被添加之前的时间点倒没有什么问题。新增的数据文件会在恢复后打开数据库时被忽略,为了避免介质恢复访问该数据文件,该数据文件可能被脱机。 6.12.4 不完全恢复后以重置日志方式打开数据库 不完全恢复后下一步就是以RESETLOGS选项打开数据库。其中一个影响(见第7节)就是数据库丢弃了不完全恢复中没用用到的重做日志,并且后续恢复将再也无法应用这些重做日志。如果是错误的进行了不完全恢复(比如说又找到了丢失的日志),下一步可以以NORESETLOGS选项打开数据库。如果打开成功了,则需要进行成功的完全恢复。 6.12.5 不完全恢复中的脱机文件 如果不完全恢复中某个数据文件处于脱机状态,它不会被恢复。如果该文件是正常脱机的表空间的一部分,不被恢复就没问题。它将一直处于脱机状态直至恢复结束。否则,如果以重置日志方式打开数据库后该数据文件仍然是脱机状态,该数据文件所在表空间将不得不被删除。因为它需要重置日志之前的日志进行介质恢复。通常在介质恢复之前都要去检查V$DATAFILE中保证数据文件都联机。只有那些是正常脱机的表空间的数据文件且该数据文件将会被删除的才能在不完全恢复中保持脱机(见8.6)。 6.13 基于备份的控制文件的恢复 如果介质恢复时控制文件比当前控制文件旧,则需要进行基于备份的控制文件的恢复(RECOVER DATABASE...USING BACKUP CONTROLFILE)。这适用于控制文件是从一个备份中还原出来的或者用CREATE CONTROLFILE...RESETLOGS命令创建的备份控制文件。 CREATE CONTROLFILE...RESETLOGS命令似的控制文件是一个“备份”。在这个命令之后只能进行基于备份控制文件的恢复,只能用RESETLOGS选项打开数据库。这个命令意味着所有的联机重做日志和控制文件备份都丢失。 相比之下,命令CREATE CONTROLFILE...NORESETLOGS使得控制文件最新。如记录了最新的联机日志和日志序号。这个命令后介质恢复不是必需的。事实上,如果是以“干净”的方式关闭并且没有数据文件是从备份中还原出来的,则不需要进行任何恢复。此后可以以正常的方式或者NORESETLOGS方式打开数据库。 一个备份的控制文件缺乏当前联机日志和数据文件结束SCN的正确信息。因此恢复进程不能找到联机日志并自动应用。并且,恢复进程还得假定结束SCN是无穷大。以RESETLOGS选项打开数据库会纠正该信息。备份的控制文件中包含的启用的线程集合可能跟原始的控制文件也不同,以RESETLOGS选项打开数据库后也会纠正该线程集合信息。 BACKUP CONTROLFILE选项可以独立使用,也可以结合不完全恢复。除非使用了不完全恢复选项,所有线程都要应用重做日志直至线程结束为止。这个会在以RESETLOGS选项打开数据库时验证。 当还原了一个备份的控制文件后,即使没有执行不完全恢复,也会要求以RESETLOGS选项打开数据库。当问题仅仅是因为丢失了当前控制文件(并且存在控制文件备份),下面步骤用来避免基于控制文件的恢复和重置日志: 1.将备份控制文件复制到当前控制文件位置,然后将数据库启动到MOUNTED状态。 2.执行ALTER DATABASE BACKUP CONTROLFILE TO TRACE NORESETLOGS. 3.执行第二步中得到跟踪文件中的SQL:CREATE CONTROLFILE...NORESETLOGS 第三步中的CREATE CONTROLFILE...NORESETLOGS命令很重要,它反映了数据库的结构信息,跟丢失的控制文件一样。如在控制文件备份后添加了一个数据文件,那么CREATE CONTROLFILE 命令就要包含该数据文件的信息。 当控制文件确实是备份的控制文件时,在RECOVER DATABASE命令时用BACKUP CONTROLFILE选项将会失败,这个很快就能检测到。一个迹象就是数据文件头的检查点计数比该数据文件在控制文件中的记录的检查点计数要大。这个测试可能也不能测不出备份控制文件,因为可能数据文件也是从备份中还原。另外一个测试是验证联机日志文件头部跟它们在控制文件中的记录,同样也可能无法测出一个备份控制文件。 6.14 创建数据文件:恢复一个备份中没有的数据文件 如果数据文件丢失或损坏了,而且还没有任何备份,它可以通过重做日志和控制文件中的记录恢复,前提是满足一下条件: 1.自该数据文件创建后的所有重做日志文件都可用。 2.包含该数据文件的信息(名称和大小等)的控制文件可用或者可以重建。 首先用ALTER DATABASE CREATE DATAFILE 创建一个新的空的数据文件以替换丢失的数据文件,然后在该数据文件上通过命令RECOVER DATAFILE 应用重做日志,从数据文件创建的时间起到丢失或损坏的那一刻为止。当期间的所有重做日志都应用后,该数据文件就跟丢失前的那一刻状态一致了。这个方法对恢复最近创建的数据文件且没有相应备份的情形很有用。不过SYSTEM表空间的原始数据文件不能用这个方法恢复,因为在数据库创建的时候还没有相应的重做日志保存下来。 6.15 用Export/Import进行即时恢复 偶尔,我们要撤销某个错误的操作(如删除表或者大量数据等)。一个途径就是执行一个在错误时间点之前的不完全恢复,然后重置日志打开数据库。这种方法就导致整个数据库--不仅仅是出错的几个SCHEMA对象--要回到一个过去的时间点。 这个方法有个副作用,就是它丢弃了提交的事务。任何发生在重置日志SCN后的更新都丢失了。重做日志的另外一个副作用就是使得之前所有的备份对将来的恢复都没有用。 因此将数据库全部回滚到过去的一个时间点并不是一个可以接受的方案。下面这个替代方案的副作用仅仅是将受影响的范围限制到恢复的几个对象。 即时不完全恢复是发生在产品数据库的副本上--称之为用于恢复的数据库。该数据库的初始状态取的是产品库发生在那个错误操作之前的备份,在副本数据库上可以将不相干的数据库对象都脱机以避免不必要的恢复。不过SYSTEM表空间和回滚段所在的表空间必须参与恢复以保证能以‘干净的’方式打开数据库。(这也说明了回滚段和数据文件应该分开存放)。 当介质恢复到错误时间之前的那一刻后,以重置日志方式打开数据库。此时数据库处于错误操作之前的一个时间点,等于有了个出错前的数据库版本。将错误操作影响的数据库对象用EXPORT导出来然后导入到产品库中。在导入到产品库之前,先做以下准备: 1.为了恢复一个错误的更新操作,在产品库把受影响的表里的数据先清除掉。如truncate表数据。 2.为了恢复一个错误的删除操作,在产品库里先重建一下被删除的对象(保持空数据)。 然后最重要的一步就是用IMPORT导入,选择只导入数据。因为EXPORT/IMPORT是一个漫长的过程,因此可以推迟到无法忍受的时间点执行。同时要恢复的对象也可以通过在产品库和副本库间建DBLINK来随时同步。 这种即时恢复的一个副作用就是跟要恢复的对象有关的事务一致性可能无法保证,不过这个副作用可以通过把要恢复的对象面扩展到跟该事务有关的所有数据库对象。 7 块修复 块修复是最简单的恢复,在数据库正常操作过程中由系统自动做的,用户几乎感觉不到。 7.1 块修复初始化和操作 前台进程在修改一个缓冲区的时候调用重做程序在该缓冲区上应用改变向量时因为前台进程僵死或者触发一个错误而导致缓冲区的状态不一致,块修复就是用来修复这种缓冲区的状态。修复的过程包括:(i)从磁盘上读取该块;(ii)用当前线程的重做日志重新构建该缓冲区的一致版本;(iii)将修复的块写回磁盘。如果块修复第一次失败了,会再尝试第二次,然后将该块标识为逻辑损坏(将该块的序号置为0),然后触发一个块损坏的错误。 块修复使用当前线程的重做日志构建缓冲区是可行的,因为: 1.块修复不能使用其他线程的重做日志或者当前线程最后一次检查点之前的重做日志。 2.直到当前线程检查点超出日志,联机日志才不会重用。 3.数据缓冲区中的都不需要从最后一次线程检查点之前的重做日志进行恢复。 7.2 缓冲区头部RBA 字段 缓冲区头(一个内存数据结构)包含下面这些跟块修复有关的字段: Low-RBA和High-RBA:Low-RBA是从该数据块最后一次块清除操作以来应用的第一个重做日志的地址,High-RBA是该数据块最新的变更对应重做日志的地址。二者结合起来描述了将该数据块从磁盘上的版本变成最新的版本所需要的重做日志范围。 Recovery-RBA:当执行块修复的是PMON进程时且完成所有的块修复可能需要很长时间就用Recover-RBA来记录进度的。 7.3 PMON 和前台进程调用 如果前台进程在回调重做日志程序时前台进程报错,将由前台进程执行块修复;如果前台进程不是报错而是僵死了,将由PMON进程执行块修复。 块修复可能需要大量的时间和I/O。不过PMON进程可以有充足的时间做块修复而忽略其他紧急任务。因此对每次PMON执行块修复使用重做日志的量有个限制(一个常量指定了每次PMON调用可以使用的重做日志块的数量)。每次PMON执行块修复应用完最大的重做日志后,都会更新数据缓冲区的Recovery-RBA字段以记录它的进度。当Recovery-RBA值达到High-RBA的值后,针对这个块的块修复过程结束。 8 重置日志(RESETLOGS) 重置日志选项用于下列情形后的第一次打开数据库的时候: 1.不完全恢复 2.基于备份控制文件的恢复 3.CREATE CONTROLFILE...RESETLOGS 重置日志的最主要的作用就是丢弃不完全恢复中没有使用的重做日志并保证后续的恢复不再需要。为此,重置日志选项将所有联机日志和归档日志都做废掉。副作用就是此前的所有备份对将来的恢复都没有用了。 重做日志选项还初始化了控制文件中关于联机日志和重做线程的内容,清除了当前存在的联机重做日志的内容,如果联机日志文件不存在就创建,并重置了所有线程的日志序号。 8.1 模糊的文件 以重做日志选项方式打开数据库时最重要的事情就是检验所有的数据文件都被恢复到同一个时间点。这保证了单笔重做日志的所有变更都自动应用了。这点对其他的一致性原因也很重要。如果所有线程重做日志都应用到所有联机数据文件上,当然可以说数据库是一致的。 如果进行了不完全恢复,有可能某个文件不是从足够旧的备份中恢复过来。通常这点可以通过检测该数据文件的头部的检查点跟其他数据文件不一致而发现(脱机文件和只读文件是例外)。 另外一种可能性就是这个文件是“模糊的”。它可能包含了超出它检查点SCN的变更。由前面章节知数据文件头部维护了下面这些“模糊状态位”来判断数据文件是否是“模糊的”: 1.联机模糊位(见3.5,6.7.2) 2.热备份模糊位(见4,6.7.3) 3.介质恢复模糊位(见6.7.1) 不完全恢复后以重置日志方式打开数据库时如果联机数据文件的模糊被设置了则会打开失败。 热备份或崩溃恢复结束时会写一笔重做日志记录使得介质恢复可以决定何时可以清除这些模糊位。重做日志会报错如果这些模糊位还没有被清除。 当数据文件中有一个数据文件结束恢复时的检查点SCN跟其他数据文件的检查点SCN(重置日志SCN,见8.2)不一致时,重置日志会报错,除非是下面这几种情形: 1.一个数据文件恢复到一个比重置SCN要早点的SCN是可以接受的,前提是该数据文件在二者之间已经没有重做日志可以应用。举例说明,该数据文件是只读的或者脱机的,且脱机范围覆盖了结束恢复时的SCN和重置SCN。这种情形下重做日志允许该数据文件设置为脱机。 2.一个数据文件做检查点的SCN比重做SCN要晚,前提是它的创建SCN(在创建数据文件的时候分配的,保存在文件头中)显示它是在重置SCN以后创建的。重做日志时检查数据字典和控制文件会发现该数据文件在数据字典中不存在但控制文件中存在。结果,它会从控制文件中被清除。 8.2 重置SCN和计数器 控制文件的数据库信息部分记录了一个重置日志的SCN和时间点(合称重置日志数据)。重置日志数据是为了唯一标识每次重做日志打开数据库的操作,同时也保存在每个数据文件头和日志文件头。日志文件中的重置日志数据如果跟控制文件中记录的不一致就不能应用该日志文件中的重做日志。数据文件中的重做日志数据如果跟控制文件中记录的不一致则该数据文件就不能被访问或者恢复,除非某些特殊情形(如该数据文件所在表空间正常脱机或者是只读的)。这保证了被重置日志丢弃的重做日志不会再被应用到数据库中,也声明了此前的任何备份对将来的恢复都是无用的。因此重做日志后立即做一个备份时聪明之举。 8.3 重置日志对线程的影响 重置日志时,每个线程的控制文件记录都清除线程打开标记并将线程检查点SCN设置到重置SCN。因此看起来线程好像在重置SCN处关闭了。控制文件中数据库信息部分记录的启用的线程列表依旧可以使用。此时哪个线程在恢复结束被启用已经不重要了,因为此前的重做日志已经不需要了。所有线程的日志序号都被置为1,其中一个线程的检查点被选为数据库检查点。 8.4 重置日志对日志文件的影响 所有联机日志都被清零,意味着所有的重做日志都被永久丢弃,除非在重做日志之前有备份联机日志,否则没有任何办法可以恢复这些联机日志。因此要恢复错误的清除联机日志的唯一方案就是联机日志有备份。要恢复一个错误的重做日志操作,必须先还原所有的数据文件、控制文件和联机日志文件,然后全部恢复。 每个启用的线程会挑选一个日志文件作为当前日志。那个日志头部将写为日志序号1.注意日志文件和相关的线程是从控制文件中取出来的(用控制文件中记录的线程号和它的日志集合)。如果这个控制文件是备份的控制文件,可能跟数据库最后一次打开的时候有点区别。 8.5 重置日志对联机数据文件的影响 所有联机数据文件头的检查点都更新为新的数据库检查点。新的重置数据会更新到各个联机数据文件头部。 8.6 重置日志对脱机数据文件的影响 脱机数据文件在控制文件中的记录显示需要做介质恢复。不过这是不可能的,因为它需要应用的重做日志的日志文件的重置数据已经不对了。这意味着包含这个数据文件的表空间必须被删除掉。有一个重要的例外就是该表空间是正常脱机的或者只读的,表空间的数据文件头中的检查点SCN都保存在TS$中,即表空间干净结束SCN(见2.17)。只要数据文件不是“模糊的”且是在表空间干净结束SCN处做的检查点,在将数据文件联机时是不需要重做日志的。此时脱机文件头部的重置数据被忽略。因此在重做日志之前正常脱机的表空间是不受它脱机期间的重做日志操作影响的。 8.7 重置日志打开数据库时对数据字典和控制文件的检查 重做日志打开数据库后,数据字典FILE$中记录的数据文件会跟控制文件中记录的数据文件进行对比。这个操作在用CREATE CONTROLFILE命令后的第一次打开数据库也会进行的。不完全恢复结束的时侯数据库中的数据文件可能跟用来恢复的控制文件中记录 数据文件不一致。使用备份的控制文件或者创建一个控制文件都有同样的问题。检查数据字典没有什么危害,因此每次数据库打开的时候都会做。不过正常情形下也要花时间去做没有什么道理。 FILE$中数据文件的入口会跟控制文件中每个数据文件号进行比较。因为FILE$反映的是数据库中的空间分配信息,它是正确的,控制文件中可能不对。如果FILE$中不存在的而控制文件中存在的数据文件将会从控制文件中清除掉。 如果一个数据文件在FILE$中存在而在控制文件中不存在,则会在控制文件中创建一个记录占位,记录在名字MISSINGnnnn下(MISSINGnnnn中nnnn是十进制形式的文件号)。MISSINGnnnn在控制文件中用来表示被脱机的文件和需要介质恢复的文件。实际文件可以通过将MISSINGnnnn重命名为实际文件名的途径来访问。 在重置打开的时候,重命名MISSINGnnnn能够访问实际数据文件的前提是该数据文件是只读的或者正常脱机的。换句话说如果重命名MISSINGnnnn为一个不是正常脱机或只读的数据文件,并不能使得该数据文件可以访问,因为它还需要重置打开数据库前的重做日志来进行介质恢复。如果是这样,这个表空间就得被删除了。 如果是因为执行了CREATE CONTROLFILE...NORESETLOGS后打开数据库时进行数据字典检查而不是因为重置打开数据库的话,需要介质恢复将该数据文件更新到最新状态。 另外一个步骤就是重复上面操作使控制文件中的数据文件记录跟数据字典中的一致。对不完全恢复而言,这个就要求还原所有的备份再重新恢复了。 9 恢复相关的 V$ 视图 V$视图包含了内核维护在内存中的数据结构的信息,可以通过有SYS权限的DBA帐号访问。下面是这些跟恢复相关的V$视图汇总: 9.1 V$LOG 包含了控制文件中的日志组信息: GROUP# THREAD# SEQUENCE# SIZE_IN_BYTES MEMBERS_IN_GROUP ARCHIVED_FLAG STATUS_OF_ GROUP (unused, current, active, inactive) LOW_SCN LOW_SCN_TIME 9.2 V$LOGFILE 包含了控制文件中的日志成员信息: GROUP# STATUS_OF_MEMBER (invalid, stale, deleted) NAME_OF_MEMBER 9.3 V$LOG_HISTORY 包含了控制文件中的日志历史记录信息: THREAD# SEQUENCE# LOW_SCN LOW_SCN_TIME NEXT_SCN 9.4 V$RECOVERY_LOG 包含了需要用来完成介质恢复用的归档日志信息(取自于控制文件中的日志历史记录信息) THREAD# SEQUENCE# LOW_SCN_TIME ARCHIVED_NAME 9.5 V$RECOVER_FILE 包含了需要进行介质恢复的数据文件及其状态 FILE# ONLINE_FLAG REASON_MEDIA_RECOVERY_NEEDED RECOVERY_START_SCN RECOVERY_START_SCN_TIME 9.6 V$BACKUP 包含了在热备份中的数据文件状态信息 FILE# FILE_STATUS (no-backup-active, backup-active, offline-normal, error) BEGIN_BACKUP_SCN BEGIN_BACKUP_TIME 10 各式各样的恢复特性 10.1 并行恢复(v7.1) 并行恢复的目标是用计算和I/O的并行机制减少崩溃恢复、单实例恢复和介质恢复的时间。当多个磁盘上多个数据文件同时进行恢复时能有效的降低恢复时间。 10.1.1 并行恢复架构 并行恢复分区做两件事: 1.读重做日志。 2.应用改变向量。 步骤1不适合并行,重做日志必须按顺序读取,然后在介质恢复中合并。因此这个任务由一个进程完成:读重做日志的进程 步骤2很适合并行,因此应用改变向量的任务就委托给一组重做程序的从属进程。重做日志读取进程将改变向量发送给重做程序从属进程,用的是跟并行查询中同样的IPC机制(进程间通讯机制)。改变向量使用HASH函数利用数据块地址做参数来分布。因此每个重做程序 进程只处理分配到它的“桶”里的改变向量。重做程序从属进程负责将数据块读入到缓存中,检查是否要应用改变向量,如果需要就应用。 这个架构达到了数据块读取I/O和改变向量应用过程中的并行。它允许日志读取I/O和数据块读取I/O可以并行进行。此外,它还允许不同HASH桶中的数据块的读取I/O可以并行进行。只要并行带来的好处比进程管理和通信带来的成本大就有效的缩减了恢复用的时间。 10.1.2 并行恢复系统初始化参数 PARALLEL_RECOVERY_MAX_THREADS PARALLEL_RECOVERY_MIN_THREADS 这两个参数控制崩溃恢复或者介质恢复中重做程序从属进程的数量。 PARALLEL_INSTANCE_RECOVERY_THREADS 这个参数控制实例恢复中重做程序从属进程的数量。 10.1.3 介质恢复语法变化 RECOVER DATABASE命令新增了一个可选参数用来指定重做程序从属进程的数量。如果指定了该参数,将覆盖默认参数PARALLEL_RECOVERY_MAX_THREADS的值。 RECOVER TABLESPACE命令新增了一个可选参数用来指定重做程序从属进程的数量。如果指定了该参数,将覆盖默认参数PARALLEL_RECOVERY_MIN_THREADS的值。 RECOVER DATAFILE命令新增了一个可选的参数用来指定重做程序从属进程的数量。如果指定了该参数,将覆盖默认参数PARALLEL_RECOVERY_MIN_THREADS的值。 10.2 重做日志 Checksums (v7.2) 日志checksum允许日志在被归档之前先检查一下是否有损坏。目的是为了防止损坏的日志被复制(归档)。这个特色将会和一个新命令 CLEAR LOGFILE 结合使用,用来清除一个损坏的联机日志而不归档。 一个新的初始化参数LOG_BLOCK_CHECKSUM控制了是否激活日志checksum功能。如果设置了,每个日志块从缓冲区中写入到磁盘之前都会计算一个值放在日志块的头部。以后该checksum值将会在归档时或者恢复的时候被验证。如果验证发现该日志块的checksum值不对,则会尝试读取该日志组的其他成员中的日志块(如果有其他成员的话)。如果所有成员都有不可避免的checksum错误,则日志读取操作失败。 如果一个不可恢复的checksum错误导致日志不能被归档,则该日志就不能被使用。最后日志切换以及产生新的日志都会延迟。如果不采取措施,数据库就会停止。CLEAR LOGFILE命令提供了一种方式避免要归档该日志。 10.3 清除日志 (v7.2) 如果一个联机日志组的所有成员都丢失或者损坏(如因为checksum错误或者介质错误等)。重做日志程序可能还可以正常进行直至要重用该日志组的时候。一旦所有线程的检查点都超出了该日志,则该日志可以被重用。但下列情形使得重用失败: 1.日志因为checksum错误而不能归档,不能归档又导致该日志不能被重用。 2.日志切换失败因为该日志不可用(如因为介质失败),该日志可能已归档或未归档。 ALTER DATABASE CLEAR LOGFILE命令用于将一个非活动状态的日志文件(即崩溃恢复不需要的日志文件)从上面这样的情形中解决出来。CLEAR LOGFILE允许有一个非活动状态的日志被清除,如丢弃并初始化,类似于先DROP LOGFILE再ADD LOGFILE。很多情形下用这个命令可以避免不必要的关闭数据库或者重置日志。 注意:CLEAR LOGFILE 不能用于清除崩溃恢复需要的联机日志(如状态为”current”或”active”的日志)。如果这样的联机日志损坏了,则需要以异常方式关闭数据库,然后做不完全恢复并以重置日志选项打开数据库。 使用UNARCHIVED选项使得日志清除过程顺利进行即使是该日志文件还没有归档。该情形下不允许用DROP LOGFILE此外CLEAR LOGFILE允许处理下列情形: 1.线程中只有两个日志组 2.在介质失败中所有日志组的成员都丢失或损坏了 3.要清除的日志是一个已关闭线程的当前日志 上面所有情形都不允许用DROP LOGFILE。 清除未归档的日志文件使得现有的备份都没有用了,因为恢复需要该日志文件。因此建议清除未归档日志后立即对数据库进行全备份。此外,UNRECOVERABLE DATAFILE选项在数据文件脱机且联机前的恢复需要该日志文件时必须结合使用。在CLEAR LOGFILE命令中带上UNRECOVERABLE DATAFILE选项,脱机的数据文件以及相应的表空间必须得从数据库中删除,因为让这个数据文件联机时恢复的日志被清除了且没有备份了。 前台进程在执行CLEAR LOGFILE时分为以下几个步骤: 1.检查该日志文件不是崩溃恢复需要的,且可以清除 2.在控制文件中将该日志标记为“正在清除”和“不需要归档”,这样该日志文件就不能够作为日志切换的候选成员了。 3.重新创建了一个新的日志文件,用多块写将其清零(一个漫长的过程)。 4.重置“正在清除”的标记。 如果前台进程在执行CLEAR LOGFILE命令中途死掉了,日志将不可用。重做日志程序将会延迟,数据库可能会停止,尤其是在日志切换的时候会发生,因为得等待检查点完成或者归档完成。假如前台进程执行CLEAR LOGFILE时真的死掉了,那应该重新执行一次。另外一个方法就是删除已经清除一部分的日志。CLEAR LOGFILE也可能在清零时因为I/O错误而失败。解决的办法就是删除该日志并重新增加一个以替换它。 |