首页
学习
活动
专区
圈层
工具
发布
社区首页 >专栏 >Oracle ADG 备库归档丢了怎么办?RMAN 增量前滚实战

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

原创
作者头像
薛晓刚-
发布于 2026-10-09 09:55:05
发布于 2026-10-09 09:55:05
90
举报

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

上次写了 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 架构(CDB$ROOT + PDB$SEED + ISLCE)
  • 同样跑在 VMware 虚拟机上

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


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

2.1 同样的开头

备库 OPEN 报的错一模一样:

代码语言:txt
复制
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 里有静态注册:

代码语言:txt
复制
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:

代码语言:sql
复制
ALTER DATABASE RECOVER MANAGED STANDBY DATABASE DISCONNECT FROM SESSION;

结果 MRP 卡住了:

代码语言:bash
复制
MRP0  WAIT_FOR_GAP  1  4923  0

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

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

代码语言:sql
复制
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:

代码语言:sql
复制
5155  YES
5156  YES
...
5163  YES
5164  NO

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

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

2.3 不是幽灵,是真的缺

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

代码语言:sql
复制
ALTER DATABASE RECOVER MANAGED STANDBY DATABASE CANCEL;
ALTER DATABASE OPEN;

OPEN 失败,同样报 ORA-10458。

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

代码语言:txt
复制
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 里还有一行:

代码语言:txt
复制
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:

代码语言:sql
复制
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 清了。

去磁盘上确认:

代码语言:bash
复制
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

代码语言:sql
复制
RECOVER STANDBY DATABASE UNTIL CANCEL;

提示:

代码语言:txt
复制
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:

代码语言:txt
复制
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

代码语言:sql
复制
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

代码语言:sql
复制
SELECT current_scn FROM v$database;
-- 752242421

4.2 主库做增量备份

代码语言:bash
复制
rman target /
RMAN> BACKUP INCREMENTAL FROM SCN 752242421
      DATABASE FORMAT '/tmp/inc_%U.bkp';

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

代码语言:bash
复制
rman target /
RMAN> SHUTDOWN IMMEDIATE;
RMAN> STARTUP MOUNT;
RMAN> CATALOG START WITH '/tmp/inc_';
RMAN> RECOVER DATABASE NOREDO;

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

4.3 为什么失败

查 RMAN 备份的元数据:

代码语言:bash
复制
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 主库重新做增量备份

代码语言:bash
复制
rman target /
RMAN> BACKUP INCREMENTAL FROM SCN 717730731
      DATABASE FORMAT '/home/oracle/inc2_%U.bkp';

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

5.2 传到备库恢复

代码语言:bash
复制
scp /home/oracle/inc2_*.bkp oracle@10.60.185.34:/tmp/

备库上:

代码语言:bash
复制
rman target /
RMAN> SHUTDOWN IMMEDIATE;
RMAN> STARTUP MOUNT;
RMAN> CATALOG START WITH '/tmp/inc2_';
RMAN> RECOVER DATABASE NOREDO;

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

5.3 OPEN + 拉起 MRP

代码语言:sql
复制
ALTER DATABASE OPEN;
ALTER DATABASE RECOVER MANAGED STANDBY DATABASE USING CURRENT LOGFILE DISCONNECT FROM SESSION;

验证:

代码语言:sql
复制
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

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

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

代码语言:sql
复制
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 保留策略:

代码语言:sql
复制
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 文件里了。

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

目录
  • 你以为和上次一样?不是,同是一台物理机上的几个虚拟机重启,但是每个环境不一样,这次主库归档没了
  • 一、环境信息
  • 二、排查:以为和上次一样,结果不一样
    • 2.1 同样的开头
    • 2.2 MRP 卡在 WAIT_FOR_GAP
    • 2.3 不是幽灵,是真的缺
    • 2.4 主库归档已经清理了
  • 三、尝试绕过 4923
    • 3.1 RECOVER UNTIL CANCEL
    • 3.2 备库 standby redo log 里有没有 4923
  • 四、RMAN 增量前滚(第一次失败)
    • 4.1 备库查 SCN
    • 4.2 主库做增量备份
    • 4.3 为什么失败
  • 五、RMAN 增量前滚(第二次成功)
    • 5.1 主库重新做增量备份
    • 5.2 传到备库恢复
    • 5.3 OPEN + 拉起 MRP
  • 六、这个坑得记住:FROM SCN 怎么取值
  • 七、和上次 rhino 库的对比
  • 八、后续要做的事
    • 8.1 修 TNS 配置
    • 8.2 监听加入开机自启
    • 8.3 主库归档保留策略
    • 8.4 备库重启标准流程
  • 九、总结
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档