因为RMAN全库备份不包含未归档的在线重做日志,导致备份结束时刻与最新状态间存在事务丢失gap;需结合在线日志拷贝或Flashback Database才能精确恢复。
为什么不能直接用 RECOVER DATABASE 恢复到备份结束时刻?
因为 rman 全库备份(backup database)默认不包含未归档的在线重做日志(即 current 或 active 日志组),而这些日志里可能有备份结束后、但尚未触发归档的已提交事务。若只靠归档日志恢复,会丢失这部分变更——这就是“备份结束时刻”和“数据库最新状态”之间的 gap。
常见错误现象:ORA-00310: archived log contains sequence 12; sequence 12 required,但 v$archived_log 查不到该序号,说明它根本没来得及归档就被覆盖或备份中断了。
- 不完全恢复(
SET UNTIL)只能停在某个归档日志结尾,无法跨过“未归档”的断点 - Flashback Database 依赖
flashback logs,但若备份前未开启FLASHBACK ON,或 flashback area 空间不足被自动清理,则不可用 - 真正能补上这个 gap 的,是还原备份 + 应用在线日志(如果还存在)+ Flashback 回退到精确 SCN/时间点
RESTORE ARCHIVELOG 能否恢复未归档的日志?
不能。RESTORE ARCHIVELOG 只处理已归档并被备份过的日志文件(即存在于备份集中、状态为 A 的 v$archived_log 记录)。未归档的在线日志(STATUS = 'CURRENT' 或 'ACTIVE')不在其作用范围内。
使用场景:当你执行了 BACKUP ARCHIVELOG ALL DELETE INPUT,又误删了部分归档,但备份集还在,这时 RESTORE ARCHIVELOG 才能从备份片中解包还原。
-
RESTORE ARCHIVELOG FROM SEQUENCE 10 UNTIL SEQUENCE 15—— 只对已归档且在备份中存在的有效 - 若
SEQUENCE 12从未归档,RMAN 会报no backup of archived log with sequence 12 - 想拿到未归档日志?唯一办法是:从原生产库的
$ORACLE_HOME/dbs或LOG_ARCHIVE_DEST_1对应路径下直接拷贝redo01.log类文件(前提是数据库未重启、日志未被覆盖)
如何用 Flashback 补齐 RMAN 不完全恢复的精度缺口?
当 RMAN 恢复只能停在最后一个可用归档日志结尾(比如 SCN 1234567),但你要回到备份刚结束时那个更精确的 SCN(比如 1234890),就得靠 Flashback Database 回滚那几十秒的差异。
前提条件必须全部满足:
- 数据库开启
FLASHBACK ON(SELECT flashback_on FROM v$database返回YES) - Flashback area(
DB_RECOVERY_FILE_DEST)空间充足,且未被自动清理掉对应时间窗口的日志 - 目标 SCN 在
V$FLASHBACK_DATABASE_LOG.OLDEST_FLASHBACK_SCN之后、GETTIME之前
实操步骤示例:
RMAN> RUN {
SET UNTIL SCN 1234567;
RESTORE DATABASE;
RECOVER DATABASE;
}
SQL> SHUTDOWN IMMEDIATE;
SQL> STARTUP MOUNT;
SQL> FLASHBACK DATABASE TO SCN 1234890;
SQL> ALTER DATABASE OPEN RESETLOGS;
最容易被忽略的三个细节
不是所有“备份结束时刻”都适合做 Flashback 目标点——它必须落在 flashback logs 的保留窗口内,而这个窗口受 DB_FLASHBACK_RETENTION_TARGET(单位分钟)和实际空间压力双重制约。
- 在线日志文件若已被覆盖(
STATUS = 'INACTIVE'但内容被新事务覆写),就永远无法找回其中的未归档事务,Flashback 也无能为力 -
RESETLOGS后旧的 flashback logs 全部失效,所以 Flashback 必须在第一次OPEN RESETLOGS前完成 - RMAN
BACKUP DATABASE PLUS ARCHIVELOG不等于“全量可恢复”,它仍不包含当前日志组;真正保险的做法是备份前先手动ALTER SYSTEM SWITCH LOGFILE,确保所有已提交事务至少落盘到一个归档中
线上环境别赌“日志还没被覆盖”,要么提前切日志,要么留好 flashback space,否则 gap 就是永久性数据丢失。










