
上次写了 rhino 库的那篇,缺 1 个 sequence,主库归档还在,修通 TNS 链路后 FAL 自动补,半小时搞定。这次是另一套环境,缺了 200 多个 sequence,主库归档也清理了,FAL 补不了。但最后还是没重做备库,RMAN 增量前滚 15 秒解决。
故障起因和上次一样:物理机故障重启,虚拟机跟着重启,备库起不来。
备库 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 被改或者换了个监听配置方式,就暴露了。这个后面再说。
链路通了,拉起 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 NO5155 到 5163 全部 applied,5164 到了但没应用。
第一反应:这是个幽灵 GAP?控制文件里残留了旧的 GAP 记录,但数据实际是连续的?
重启 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-5022Crash 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 = 717730731datafile 的数据块实际已经更新到了 752339286(接近主库当前 SCN 752340840),但 checkpoint 信息还停在 717730731。Crash Recovery 要从 checkpoint SCN 开始,需要 4923 的 redo,等不到就卡住。
去主库查 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_184923 的完成时间是 7 月 29 日,主库 FRA 里最早只保留到 9 月 18 日的 5123。中间两个月的归档全清了。
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。绕不过去。
SELECT group#, thread#, sequence#, bytes, archived, status
FROM v$standby_log ORDER BY group#;最早的 standby redo log 是 sequence 5165,4923 早就被覆盖了。
走不通。4923 的归档主库备库都没有,只能走 RMAN 增量 SCN 前滚。
SELECT current_scn FROM v$database;
-- 752242421rman 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。
查 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 target /
RMAN> BACKUP INCREMENTAL FROM SCN 717730731
DATABASE FORMAT '/home/oracle/inc2_%U.bkp';这次备份 15 秒完成,三个文件加起来约 1.9GB。比上次大很多,因为覆盖了从 7 月 29 日到 9 月 28 日两个月的增量数据。
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 真正执行了,不是一秒结束。
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 rowsADG 完全恢复。
这是这次最核心的教训。
很多人写 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 库 (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 就卡住了。
主库 tnsnames.ora 里 orcl_sty 别名的 SERVICE_NAME = orcl,改成 orcl_sty。现在靠 listener.ora 静态注册撑着,但静态注册的 status = UNKNOWN,有些场景下会有问题(比如 listener 重启后静态注册的服务需要手动 reload)。
和 rhino 库一样的建议。检查 /etc/oratab 和 dbstart 脚本,确保监听随实例一起启动。
这个库主库 FRA 50GB,归档只保留了 10 天(最早 9 月 18 日的 5123)。4923 是 7 月 29 日的,早就清了。
建议调整 RMAN 保留策略:
RMAN> CONFIGURE RETENTION POLICY TO RECOVERY WINDOW OF 30 DAYS;或者至少确保备库 GAP 检测能及时发现缺失——如果 GAP 发现得早,主库归档还没被清理,走路径A 就能解决,不用走路径C。
和 rhino 库一样,不重复了。核心原则:先停 MRP 再 shutdown,先起监听再 OPEN。
这已经是10多年没做处置过这类问题了。以后让AI来做吧。
datafile 的 checkpoint SCN 才是 Crash Recovery 的起点,FROM SCN 必须从这里开始。这个已经更新到 skill 文件里了。
原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。
如有侵权,请联系 cloudcommunity@tencent.com 删除。