Oracle ADG 备库归档丢了怎么办?RMAN 增量前滚实战

你以为和上次一样?不是,同是一台物理机上的几个虚拟机重启,但是每个环境不一样,这次主库归档没了

上次写了 rhino 库的那篇,缺 1 个 sequence,主库归档还在,修通 TNS 链路后 FAL 自动补,半小时搞定。这次是另一套环境,缺了 200 多个 sequence,主库归档也清理了,FAL 补不了。但最后还是没重做备库,RMAN 增量前滚 15 秒解决。


一、环境信息

  • 主库:prod-islce-18533(db_unique_name=orcl_pri)
  • 备库:prod-islce-18534(db_unique_name=orcl_sty)
  • Oracle 19.3.0.0.0,CDB 架构(CDBROOT+PDBROOT+PDBSEED + ISLCE)
  • 同样跑在 VMware 虚拟机上

故障起因和上次一样:物理机故障重启,虚拟机跟着重启,备库起不来。


二、排查:以为和上次一样,结果不一样

2.1 同样的开头

备库 OPEN 报的错一模一样:

复制代码
ORA-10458: standby database requires recovery
ORA-01196: file 1 is inconsistent due to a failed media recovery session
ORA-01110: data file 1: '/data/app/oracle/oradata/ORCL/system01.dbf'

先按上次的流程走:查 MRP、查 GAP、查监听、查 TNS。

监听确实没起来,lsnrctl start 后服务注册正常。但这次主库 v$archive_dest 的 dest_id=2 直接就是 VALID------没报 ORA-12514。

为什么?因为备库 listener.ora 里有静态注册:

复制代码
SID_LIST_LISTENER =
  (SID_LIST =
    (SID_DESC =
      (GLOBAL_DBNAME = orcl)
      (ORACLE_HOME = /data/app/oracle/product/19.3.0/db_1)
      (SID_NAME = orcl)
    )
  )

监听一启动就有 orcl 服务(status UNKNOWN,静态注册的标志)。主库 tnsnames.ora 里 orcl_sty 别名的 SERVICE_NAME = orcl,正好匹配上了。所以主库能连备库,dest_id=2 = VALID。

但这个静态注册只是掩盖了 TNS 配置的隐患------和 rhino 库一样,SERVICE_NAME 应该写 orcl_sty(db_unique_name)而不是 orcl(db_name)。平时靠静态注册撑着,一旦 listener.ora 被改或者换了个监听配置方式,就暴露了。这个后面再说。

2.2 MRP 卡在 WAIT_FOR_GAP

链路通了,拉起 MRP:

复制代码

ALTER DATABASE RECOVER MANAGED STANDBY DATABASE DISCONNECT FROM SESSION;

结果 MRP 卡住了:

复制代码
MRP0  WAIT_FOR_GAP  1  4923  0

在等 4923。查 v$archive_gap------no rows。但 MRP 确实卡在 4923 不走。

这时候看了一眼备库的 v$archived_log:

复制代码

SELECT sequence#, applied FROM v$archived_log WHERE sequence# BETWEEN 4920 AND 4930 AND thread#=1 ORDER BY sequence#;

4920~4930 全部 applied=YES。包括 4923。

再看 5155~5164:

复制代码

5155 YES 5156 YES ... 5163 YES 5164 NO

5155 到 5163 全部 applied,5164 到了但没应用。

第一反应:这是个幽灵 GAP?控制文件里残留了旧的 GAP 记录,但数据实际是连续的?

2.3 不是幽灵,是真的缺

重启 MRP 试了两次,还是 WAIT_FOR_GAP 4923。不管它,直接 OPEN 试试:

复制代码

ALTER DATABASE RECOVER MANAGED STANDBY DATABASE CANCEL; ALTER DATABASE OPEN;

OPEN 失败,同样报 ORA-10458。

看 alert 日志和 trc 文件,找到关键信息:

复制代码
Start recovery at thread 1 ckpt scn 717730731 logseq 4923 block 2
Media Recovery Waiting for T-1.S-4923
Fetching gap from T-1.S-4923 to T-1.S-5022

Crash Recovery 从 datafile 的 checkpoint SCN 开始恢复,这个 SCN 是 717730731,对应 logseq 4923。也就是说 datafile 的文件头记录的恢复起点就是 4923,不是控制文件里的 GAP 记录在作怪。

v$archived_log 里 4923 applied=YES 只代表归档曾经注册过,datafile 的 checkpoint 没有推进到 5163。trc 里还有一行:

复制代码
Highest datafile fuzzy SCN: 0x000000002cd64f56    = 752339286
In-flux buffer recovery target SCN: 0x000000002ac7b3ab  = 717730731

datafile 的数据块实际已经更新到了 752339286(接近主库当前 SCN 752340840),但 checkpoint 信息还停在 717730731。Crash Recovery 要从 checkpoint SCN 开始,需要 4923 的 redo,等不到就卡住。

2.4 主库归档已经清理了

去主库查 4923:

复制代码

SELECT sequence#, name, archived, deleted, status FROM v$archived_log WHERE sequence# = 4923 AND thread# = 1;

v$archived_log 里有两行:dest_id=2 那条 DEL=NO,dest_id=1 那条 DEL=YES。本地归档已经被 RMAN 清了。

去磁盘上确认:

复制代码

ls /data/app/oracle/fast_recovery_area/ORCL_PRI/archivelog/ | sort | head # 最早的目录是 2026_09_18

4923 的完成时间是 7 月 29 日,主库 FRA 里最早只保留到 9 月 18 日的 5123。中间两个月的归档全清了。


三、尝试绕过 4923

3.1 RECOVER UNTIL CANCEL

复制代码

RECOVER STANDBY DATABASE UNTIL CANCEL;

提示:

复制代码
ORA-00279: change 717730731 generated at 07/28/2026 22:01:14 needed for thread 1
ORA-00289: suggestion : /data/app/oracle/fast_recovery_area/ORCL_STY/archivelog/2026_09_28/o1_mf_1_4923_%u_.arc
ORA-00280: change 717730731 for thread 1 is in sequence #4923

Specify log: {<RET>=suggested | filename | AUTO | CANCEL}

输入 CANCEL:

复制代码
ORA-01547: warning: RECOVER succeeded but OPEN RESETLOGS would get error below
ORA-01196: file 1 is inconsistent due to a failed media recovery session
ORA-01112: media recovery not started

没恢复任何东西,datafile 还是 fuzzy。绕不过去。

3.2 备库 standby redo log 里有没有 4923

复制代码

SELECT group#, thread#, sequence#, bytes, archived, status FROM v$standby_log ORDER BY group#;

最早的 standby redo log 是 sequence 5165,4923 早就被覆盖了。

走不通。4923 的归档主库备库都没有,只能走 RMAN 增量 SCN 前滚。


四、RMAN 增量前滚(第一次失败)

4.1 备库查 SCN

复制代码

SELECT current_scn FROM v$database; -- 752242421

4.2 主库做增量备份

复制代码

rman target / RMAN> BACKUP INCREMENTAL FROM SCN 752242421 DATABASE FORMAT '/tmp/inc_%U.bkp';

三个文件,加起来 113MB。挺小,传到备库恢复:

复制代码

rman target / RMAN> SHUTDOWN IMMEDIATE; RMAN> STARTUP MOUNT; RMAN> CATALOG START WITH '/tmp/inc_'; RMAN> RECOVER DATABASE NOREDO;

一秒结束。OPEN------还是 ORA-10458。

4.3 为什么失败

查 RMAN 备份的元数据:

复制代码
File LV Type Ckp SCN Ckp Time
 1 Incr 752369696 2026:09:2815:45:21

备份的 Ckp SCN 是 752369696。但 datafile 的 checkpoint SCN 是 717730731。

BACKUP INCREMENTAL FROM SCN 752242421 做出来的备份只包含 752242421 之后的增量块。datafile 需要的是 717730731→752242421 之间的 redo,这些在备份里根本没有。NOREDO 恢复发现备份覆盖的范围对不上 datafile 的缺口,跳过了。

正确做法:FROM SCN 要用 datafile 的 checkpoint SCN(717730731),不是备库的 current_scn(752242421)。


五、RMAN 增量前滚(第二次成功)

5.1 主库重新做增量备份

复制代码

rman target / RMAN> BACKUP INCREMENTAL FROM SCN 717730731 DATABASE FORMAT '/home/oracle/inc2_%U.bkp';

这次备份 15 秒完成,三个文件加起来约 1.9GB。比上次大很多,因为覆盖了从 7 月 29 日到 9 月 28 日两个月的增量数据。

5.2 传到备库恢复

复制代码

scp /home/oracle/inc2_*.bkp oracle@10.60.185.34:/tmp/

备库上:

复制代码

rman target / RMAN> SHUTDOWN IMMEDIATE; RMAN> STARTUP MOUNT; RMAN> CATALOG START WITH '/tmp/inc2_'; RMAN> RECOVER DATABASE NOREDO;

这次 RECOVER 真正执行了,不是一秒结束。

5.3 OPEN + 拉起 MRP

复制代码

ALTER DATABASE OPEN; ALTER DATABASE RECOVER MANAGED STANDBY DATABASE USING CURRENT LOGFILE DISCONNECT FROM SESSION;

验证:

复制代码

SELECT name, database_role, open_mode FROM v$database; -- ORCL PHYSICAL STANDBY READ ONLY WITH APPLY SELECT process, status, thread#, sequence#, delay_mins FROM v$managed_standby WHERE process LIKE 'MRP%'; -- MRP0 APPLYING_LOG 1 5165 0 SELECT * FROM v$archive_gap; -- no rows

ADG 完全恢复。


六、这个坑得记住:FROM SCN 怎么取值

这是这次最核心的教训。

很多人写 RMAN 增量前滚的时候,FROM SCN 用的是备库的 current_scn。这在某些场景下是对的------比如备库是全新搭建的、或者 datafile 的 checkpoint SCN 和 current_scn 差距不大的时候。

但在备库运行了很久、datafile checkpoint 远低于 current_scn的场景下,就会出问题。如下表所示。

取值方式 FROM SCN 覆盖范围 结果
备库 current_scn 752242421 752242421→752369696 datafile 缺口 717730731→752242421 没覆盖,失败
datafile checkpoint SCN 717730731 717730731→752369696 完整覆盖 datafile 缺口,成功

datafile 的 checkpoint SCN 从哪获取:

方法一:查 trc 文件,搜 Start recovery at thread 1 ckpt scn

复制代码
Start recovery at thread 1 ckpt scn 717730731 logseq 4923 block 2

方法二:查 v$datafile_header(注意 19c 没有 last_change# 列):

复制代码

SELECT file#, status, fuzzy, checkpoint_change# FROM v$datafile_header ORDER BY file#;

取最小的 checkpoint_change# 就是要恢复的起点。


七、和上次 rhino 库的对比

对比项 rhino 库 (177/178) orcl 库 (33/34)
Oracle 版本 11.2.0.4 19.3.0.0.0
缺失归档数量 1 个(seq 53800) 200+ 个(seq 4923~5122)
主库归档是否还在 在 不在(已清理)
恢复路径 路径A:修通链路后 FAL 自动补 路径C:RMAN 增量 SCN 前滚
TNS SERVICE_NAME 隐患 有,已修复 有,靠 listener.ora 静态注册掩盖,尚未修复
listener.ora 静态注册 无 有(GLOBAL_DBNAME=orcl)
增量备份大小 不适用 1.9GB
恢复耗时 约 30 分钟 约 15 分钟(备份+传输+恢复)

两套环境,两个坑,但根因是一样的:监听没加入开机自启。物理机重启后监听没跟着起来,redo 传不过去,备库重启时 Crash Recovery 缺 redo 就卡住了。


八、后续要做的事

8.1 修 TNS 配置

主库 tnsnames.ora 里 orcl_sty 别名的 SERVICE_NAME = orcl,改成 orcl_sty。现在靠 listener.ora 静态注册撑着,但静态注册的 status = UNKNOWN,有些场景下会有问题(比如 listener 重启后静态注册的服务需要手动 reload)。

8.2 监听加入开机自启

和 rhino 库一样的建议。检查 /etc/oratab 和 dbstart 脚本,确保监听随实例一起启动。

8.3 主库归档保留策略

这个库主库 FRA 50GB,归档只保留了 10 天(最早 9 月 18 日的 5123)。4923 是 7 月 29 日的,早就清了。

建议调整 RMAN 保留策略:

复制代码

RMAN> CONFIGURE RETENTION POLICY TO RECOVERY WINDOW OF 30 DAYS;

或者至少确保备库 GAP 检测能及时发现缺失------如果 GAP 发现得早,主库归档还没被清理,走路径A 就能解决,不用走路径C。

8.4 备库重启标准流程

和 rhino 库一样,不重复了。核心原则:先停 MRP 再 shutdown,先起监听再 OPEN。


九、总结

这已经是10多年没做处置过这类问题了。以后让AI来做吧。

datafile 的 checkpoint SCN 才是 Crash Recovery 的起点,FROM SCN 必须从这里开始。这个已经更新到 skill 文件里了。

相关推荐
Highcharts.js3 小时前
用Highcharts开发动态主从图表|双图联动的时间序列图表示例
javascript·数据库·信息可视化·highcharts·图表开发·动态图表
阿俊-全栈开发3 小时前
LikeShop 版本升级与备份:从旧版平滑迁移的完整步骤
jvm·数据库·oracle·开源·likeshop·likeshop开源商城
姜鱼问生4 小时前
docker exec 排查容器问题:从日志到进程
运维·网络·数据库·docker·容器
狗凯之家源码网5 小时前
AI 步数修改提交系统源码应用场景与落地指南
android·数据库·人工智能·运动步数
穆梓兰煊5 小时前
AI供应链安全不再只是包安全,还涉及模型与数据
前端·数据库
北风toto5 小时前
数据库笔记:Armstrong 公理系统与集合论的深度辨析
数据库·笔记
小蒜学长5 小时前
基于SpringBoot+Vue的租房管理系统的设计与实现(代码+数据库+LW)
java·数据库·spring boot·后端·租房管理
一只专注api接口开发的技术猿5 小时前
Open‑Claw 实战|告别页面逆向,快速搭建电商商品监控与数据分析完整方案
大数据·数据库·python·数据挖掘·数据分析