14.7 闪回数据库(1)
闪回数据库的命令是"flashback database to <PIT>",<PIT>可以是SCN、时间或还原点,顾名思义,就是将整个数据库回退到指定的一个时间点,实际上是数据库不完全恢复的另一种方式。真正的不完全恢复需要消耗的时间与数据库的大小有密切联系,数据库越庞大,需要的时间就越多,对于大型数据库来说,哪怕是只为了回到30秒之前,消耗的时间也是惊人的。
闪回数据库技术改变了这个窘境,其处理问题方式可以着重于如何将相对较短的时间内发生的变更去除,而不是如何还原足够旧的备份(这已经很花时间了),再利用归档日志前滚至指定时间。闪回的"闪"字用在这里显得十分贴切。
闪回数据库需要使用两种日志:闪回日志和重做日志。其中重做日志已为大家所知,而闪回日志就像是重做日志的反作用力,闪回日志的记载正好与重做日志的记载相反。比如,逻辑上重做日志记录insert命令的重做记录,闪回日志就记录delete命令的重做记录(当然实际上没那么简单)。在发起闪回操作时,只要根据写入闪回日志的相反顺序,即后写先读的顺序,将闪回记录从闪回日志读出并执行其记录的变更就能够将数据库在时间轴上倒推。
闪回日志的保存路径一定是快速恢复区的子目录,保存的期限则由参数db_flashback_ retention_target控制(单位为分钟),凡是超出保存期限的闪回日志将会在快速恢复区空间紧张的时候被自动删除。比如,指定数据库保留两天的闪回日志和归档日志:
- SQL> alter system set db_flashback_retention_target=2880;
- System altered.
使用v$database.FLASHBACK_ON可以查看闪回日志是否已启用,现在是"NO",表示尚未启用:
- SQL> select flashback_on from v$database;
- FLASHBACK_ON
- ------------------
- NO
在确保启用了归档模式之后,使用以下命令可以启用闪回日志,即闪回数据库功能:
- SQL> alter database flashback on;
- Database altered.
从此,在快速恢复区的flashback子目录下将会出现扩展名为.flb的文件,它们就是闪回日志。
- SQL> select flashback_on from v$database;
- FLASHBACK_ON
- ------------------
- YES
闪回数据库命令的语法很简单:在进入MOUNT状态后执行"flashback database to scn …"或"flashback database to timestamp …"。
一次闪回数据库操作可能由两种方式进行。比如,令当前时间点为TC,数据库闪回的目标时间点为T1(TC大于T1),使用的命令为"flashback database to timestamp <T1>",该命令会自动选择以下两种方式的其中一个进行闪回操作。
方式一:
(1)第一阶段:利用闪回日志将数据库从TC"倒推"至较T1更旧的某一时刻T2。
(2)第二阶段:利用重做日志将数据库从T2"前滚"至T1。
方式二:
(1)第一阶段:确定一个比T1更旧的某一时刻T2。
(2)第二阶段:对于闪回日志根本无法恢复的对象或数据,令当初此类对象第一次产生的时间为T3,首先利用T3到T2的重做日志将其重新产生并恢复。
(3)第三阶段:利用闪回日志将数据库从TC"倒推"至T2。
(4)第四阶段:利用重做日志将数据库从T2"前滚"至T1(途中经过T2)。
究竟采用哪种方式执行取决于目标时间点T1与当前时间点TC之间执行过什么命令,如果是在闪回日志中有对应反向操作的命令(如insert、update、delete)就采用方式一;如果在闪回日志中找不到对应反向操作的命令(比如:truncate命令,难道截断1亿行的表时让Oracle在闪回日志中记录1亿行?这种重做日志和闪回日志严重失衡的事情是不会发生的)则采用方式二。方式二较方式一可能会索要更多的重做日志才可以完成闪回。
比如,若有任何对象发生过截断操作(truncate table …),那么方式二中的T3就是当初创建被截断的表的时刻,这意味着整个闪回操作需要从T3至T1的所有的重做日志,否则闪回数据库不可能成功。这样,可能会发生这样的问题:即使只是在10秒前错误地截断了一张表,现需要回到10秒之前,但是闪回数据库时"flashback database"命令向管理员索要一年前的归档日志!
14.7 闪回数据库(2)
悲观情绪不必过度蔓延,如果T1和TC之间只是发生过类似update那样的DML,若是想回到10秒前,那么会采用方式一,差不多只是需要10秒的闪回日志和归档日志,闪回会很快,这也是闪回的真谛。
无论哪种方式,都可能遇到重做日志不充分的问题,报错信息类似如下所示:
- SQL> flashback database to scn 1036988;
- flashback database to scn 1036988
- *
- ERROR at line 1:
- ORA-38754: FLASHBACK DATABASE not started; required redo log is not available
- ORA-38762: redo logs needed for SCN 1036814 to SCN 1036988
- ORA-38761: redo log sequence 19 in thread 1, incarnation 2 could not be accessed
也可能遇到闪回日志不够的问题,报错信息如下所示:
- SQL> flashback database to scn 1036988;
- flashback database to scn 1036988
- *
- ERROR at line 1:
- ORA-38729: Not enough flashback database log data to do FLASHBACK.
现在讨论一下具体的闪回步骤应该如何操作。在发起闪回操作前,推荐查看一下v$flashback_database_log视图,检查最远可以回到哪里:
- SQL> select oldest_flashback_scn,
- 2 to_char(oldest_flashback_time,'YYYY-MM-DD HH24:MI:SS')
- 3 from v$flashback_database_log;
- OLDEST_FLASHBACK_SCN TO_CHAR(OLDEST_FLAS
- -------------------- -------------------
- 1041426 2011-10-17 02:57:34
进入MOUNT状态发起闪回操作后,管理员可以反复地以任何顺序执行这3个命令:"flashback database to …"、"recover database"和"alter database open read only"。比如,先进入数据库的MOUNT状态:
- SQL> startup force mount;
- 回到SCN号1041440:
- SQL> flashback database to scn 1041440;
- Flashback complete.
以只读形式打开数据库,这样就可以查看SCN在1041440时数据库中的所有数据,以便判断闪回操作是否达到目的:
- SQL> alter database open read only;
- Database altered.
若嫌数据库不够"旧",可以回到MOUNT状态,然后使用更低的SCN再次执行flashback,比如:
- SQL> startup force mount;
- SQL> flashback database to scn 1041430;
- Flashback complete.
再将数据库以只读形式打开,观察结果:
- SQL> alter database open read only;
- Database altered.
这次若嫌数据库不够"新",可以回到MOUNT状态使用更高的SCN号再度执行flashback,此时该操作实际上干脆只使用重做日志了,比如:
- SQL> startup force mount;
- SQL> flashback database to scn 1042000;
- Flashback complete.
然后再将数据库以只读形式打开,观察结果,如此循环,直到获得满意的结果为止。最后以resetlogs方式打开数据库,效果和不完全恢复一模一样:
- SQL> startup force mount;
- SQL> alter database open resetlogs;
- Database altered.