一、问题背景
在 Oracle 19c RAC/ODA 环境进行日常备份巡检时,发现 NFS 备份目录中长期残留大量历史 RMAN 备份文件。
按照原有备份保留策略,超过保留周期的备份理论上应该被自动清理,但实际发现:
-
NFS 中十几天前的 Backup Piece 仍然存在;
-
RMAN 无法正常按照时间范围识别部分历史备份;
-
旧备份长期无法清理,导致 NFS 空间持续增长。
原脚本中存在类似按时间直接清理历史备份的逻辑:
DELETE NOPROMPT BACKUP COMPLETED BEFORE 'SYSDATE-14';
但实际执行时出现:
specification does not match any backup in the repository
由此开始排查 RMAN Repository 与控制文件中的历史备份记录。
二、问题现象
首先检查 NFS 备份目录,可以确认历史 Backup Piece 文件实际仍然存在:
ERPCDB_01_DATAFILE_20260812_...
ERPCDB_01_DATAFILE_20260813_...
ERPCDB_01_DATAFILE_20260814_...
...
但在 RMAN 中按照时间范围查询这些历史备份时,却无法正常识别。
进一步检查其中一个历史 Backup Set,发现:
V$BACKUP_SET 有记录
V$BACKUP_PIECE 有记录
V$BACKUP_DATAFILE 无对应记录
例如:
SELECT
bs.recid,
TO_CHAR(bs.completion_time,'YYYY-MM-DD HH24:MI:SS') completion_time,
COUNT(bd.file#) datafile_records
FROM v$backup_set bs
LEFT JOIN v$backup_datafile bd
ON bd.set_stamp = bs.set_stamp
AND bd.set_count = bs.set_count
WHERE bs.recid = 6584
GROUP BY
bs.recid,
bs.completion_time;
结果中:
DATAFILE_RECORDS = 0
说明:
Backup Set 和 Backup Piece 的部分记录还存在,但数据文件备份的详细元数据已经丢失。
此时问题已经不再是简单的"DELETE 为什么没执行",而是:
为什么 RMAN 的历史备份元数据提前丢失了?
三、排查分析
1. 确认 RMAN Repository 存储位置
当前环境没有使用独立的 RMAN Recovery Catalog。
因此 RMAN 的历史备份信息主要保存在数据库 Control File 中。
这意味着:
Control File 中 RMAN Metadata 的保留能力
会直接影响 RMAN 对历史备份的识别和管理。
2. 检查 CONTROL_FILE_RECORD_KEEP_TIME
检查参数:
SHOW PARAMETER control_file_record_keep_time;
发现:
CONTROL_FILE_RECORD_KEEP_TIME = 7
该参数用于控制:
Control File 中可循环复用记录,在被重新使用之前至少保留多少天。
RMAN 相关记录包括:
BACKUP SET
BACKUP PIECE
BACKUP DATAFILE
BACKUP REDOLOG
ARCHIVED LOG
如果这些记录达到可复用条件,Oracle 就可能重新使用对应记录槽位。
因此可能出现:
Backup Piece物理文件仍然存在
↓
Control File中的部分RMAN元数据已经被覆盖
↓
RMAN无法完整识别历史备份
↓
历史文件无法正常通过RMAN清理
3. 检查 Control File Record Section
进一步检查:
SELECT
type,
records_total,
records_used
FROM v$controlfile_record_section
WHERE type IN (
'ARCHIVED LOG',
'BACKUP SET',
'BACKUP PIECE',
'BACKUP DATAFILE',
'BACKUP REDOLOG'
);
现场发现多个 RMAN Record Section:
RECORDS_USED = RECORDS_TOTAL
这本身并不代表控制文件异常,因为这些区域本来就是循环使用的。
但结合:
CONTROL_FILE_RECORD_KEEP_TIME = 7
以及历史 V$BACKUP_DATAFILE 记录已经消失,可以判断:
Control File 中的历史 RMAN Metadata 已经发生循环复用。
四、问题定位
最终问题链路可以概括为:
每天产生大量RMAN备份记录
↓
CONTROL_FILE_RECORD_KEEP_TIME仅7天
↓
历史RMAN记录较早进入可复用状态
↓
部分Backup Datafile元数据被覆盖
↓
NFS上的Backup Piece仍然存在
↓
RMAN无法完整识别这些历史备份
↓
DELETE/LIST无法正常管理
↓
历史备份长期残留
↓
NFS空间持续增长
最终根因:
RMAN 实际备份保留周期,与 Control File 中 RMAN Metadata 的保留周期不匹配。
五、相关整改
1. 调整 CONTROL_FILE_RECORD_KEEP_TIME
整改后计划采用:
RMAN Recovery Window = 14天
如果仍然保持:
CONTROL_FILE_RECORD_KEEP_TIME = 7天
就会出现:
希望RMAN管理14天的恢复窗口
↓
但RMAN元数据7天后就可能被复用
因此最终调整为:
CONTROL_FILE_RECORD_KEEP_TIME = 21天
RMAN Recovery Window = 14天
即:
14天恢复窗口
+
7天RMAN元数据缓冲
=
21天
RAC 环境只需要在任意一个实例执行一次:
ALTER SYSTEM SET control_file_record_keep_time=21
SCOPE=BOTH
SID='*';
其中:
SID='*'
表示使用 RAC 全局配置。
SCOPE=BOTH
表示同时修改当前运行参数和 SPFILE。
该参数支持动态修改,因此无需重启数据库。
修改后通过:
SELECT inst_id, value
FROM gv$parameter
WHERE name = 'control_file_record_keep_time'
ORDER BY inst_id;
确认两个 RAC 实例均为:
21
2. 修改 RMAN Retention Policy
原环境:
CONFIGURE RETENTION POLICY TO REDUNDANCY 1;
调整为:
CONFIGURE RETENTION POLICY TO RECOVERY WINDOW OF 14 DAYS;
检查:
SHOW RETENTION POLICY;
应看到:
CONFIGURE RETENTION POLICY TO RECOVERY WINDOW OF 14 DAYS;
整改后形成:
CONTROL_FILE_RECORD_KEEP_TIME = 21天
>
RECOVERY WINDOW = 14天
3. 为什么不再按 SYSDATE 硬删除全备?
原脚本类似:
DELETE BACKUP COMPLETED BEFORE 'SYSDATE-14';
这种方式主要按照 Backup 完成时间进行删除。
整改后改为:
DELETE NOPROMPT OBSOLETE;
由 RMAN 根据:
RECOVERY WINDOW OF 14 DAYS
判断哪些 Backup 已经不再需要。
需要特别注意:
RECOVERY WINDOW OF 14 DAYS
并不等于:
超过14天的文件全部删除
RMAN 可能仍然需要某个更早的 Full Backup 作为恢复窗口的基线,因此这个 Backup 可能继续保留。
所以:
RECOVERY WINDOW + DELETE OBSOLETE
比固定日期硬删除更符合 RMAN 的备份生命周期管理机制。
六、历史异常备份处理
修改参数只能避免未来继续出现同类问题。
对于之前已经发生元数据丢失的历史 Backup Piece:
物理文件仍然存在
+
RMAN元数据已经不完整
无法通过修改参数自动恢复这些历史 Repository 信息。
因此需要进行一次性专项清理。
本次首先确认:
当前可正常识别的备份起始时间
历史异常文件范围
当前恢复保留需求
随后将确认不再需要的历史异常 Backup Piece 清理。
清理完成后:
历史异常Backup Piece:已清理
历史残留文件:0
剩余Backup:AVAILABLE
NFS空间恢复正常
此类历史异常文件只需要专项处理一次。
后续正常备份不再通过操作系统按时间清理,而统一交给 RMAN:
DELETE OBSOLETE;
七、整改后的 RMAN 脚本
脚本整改主要有三个重点。
1. 删除原来的时间硬删除逻辑
取消类似:
DELETE BACKUP COMPLETED BEFORE 'SYSDATE-7';
DELETE BACKUP COMPLETED BEFORE 'SYSDATE-14';
统一使用:
DELETE NOPROMPT OBSOLETE;
2. 主库 RMAN 核心逻辑
最终核心逻辑如下:
RUN {
ALLOCATE CHANNEL c1 DEVICE TYPE DISK;
ALLOCATE CHANNEL c2 DEVICE TYPE DISK;
ALLOCATE CHANNEL c3 DEVICE TYPE DISK;
ALLOCATE CHANNEL c4 DEVICE TYPE DISK;
CROSSCHECK BACKUP;
CROSSCHECK ARCHIVELOG ALL;
DELETE NOPROMPT EXPIRED ARCHIVELOG ALL;
DELETE NOPROMPT EXPIRED BACKUP;
DELETE NOPROMPT OBSOLETE;
SQL 'ALTER SYSTEM ARCHIVE LOG CURRENT';
BACKUP AS COMPRESSED BACKUPSET DATABASE
FORMAT '/backup_nfs/oracle/rman/%d_01_DATAFILE_%T_%U';
BACKUP AS COMPRESSED BACKUPSET ARCHIVELOG ALL
FORMAT '/backup_nfs/oracle/rman/%d_02_ARCHIVELOG_%T_%s_%U';
BACKUP AS COMPRESSED BACKUPSET CURRENT CONTROLFILE
FORMAT '/backup_nfs/oracle/rman/%d_03_CONTROLFILE_%T_%p_%s_%U';
BACKUP AS COMPRESSED BACKUPSET SPFILE
FORMAT '/backup_nfs/oracle/rman/%d_04_SPFILE_%T_%U';
DELETE NOPROMPT ARCHIVELOG
UNTIL TIME 'SYSDATE-3'
BACKED UP 1 TIMES TO DISK;
DELETE NOPROMPT OBSOLETE;
RELEASE CHANNEL c1;
RELEASE CHANNEL c2;
RELEASE CHANNEL c3;
RELEASE CHANNEL c4;
}
清理逻辑最终分成三类:
EXPIRED
→ RMAN有记录,但实际文件已经不存在
OBSOLETE
→ 文件存在,但根据14天Recovery Window已经不再需要
ARCHIVELOG
→ 超过3天并且至少已经备份1次后删除
3. 增加 NFS 挂载检查
在执行 RMAN 之前增加:
检查NFS是否真正挂载
检查RMAN目录是否存在
检查RMAN目录是否可写
如果任意一项异常:
立即停止备份脚本
主要防止:
NFS掉挂
↓
RMAN写入本地挂载点目录
↓
数据库服务器本地磁盘被写满
↓
影响数据库稳定运行
八、整改后的最终关系
整改完成后的整体策略:
CONTROL_FILE_RECORD_KEEP_TIME
21天
│
▼
RMAN Metadata保留
│
▼
RECOVERY WINDOW OF 14 DAYS
│
▼
DELETE OBSOLETE
│
▼
自动管理历史全备
主库归档:
超过3天
+
已备份至少1次
=
删除
ADG 备库:
本地归档保留3天
脚本日志:
保留14天
九、以后遇到同类问题怎么快速排查?
以后如果再次遇到:
物理Backup Piece明明存在
但是RMAN查询不到
或者DELETE无法正常清理
按照下面顺序检查即可:
① 查看物理Backup Piece是否存在
↓
② RMAN LIST能否正常识别历史Backup
↓
③ 检查V$BACKUP_SET
↓
④ 检查V$BACKUP_PIECE
↓
⑤ 检查V$BACKUP_DATAFILE是否还有明细
↓
⑥ 检查CONTROL_FILE_RECORD_KEEP_TIME
↓
⑦ 检查RMAN RETENTION POLICY
↓
⑧ 判断Metadata保留周期是否小于实际备份保留需求
最关键的判断是:
Backup Set有记录
Backup Piece有记录
Backup Datafile已经没有记录
出现这种情况时,就要重点怀疑:
Control File 中 RMAN 历史元数据已经发生循环覆盖。
而不是继续反复修改 DELETE 命令。
十、总结
本次问题表面现象是:
历史RMAN备份无法正常清理
实际问题是:
CONTROL_FILE_RECORD_KEEP_TIME过短
↓
RMAN历史Metadata提前被循环复用
↓
Backup Piece仍在
但RMAN已经无法完整识别
↓
历史文件长期残留
最终整改:
CONTROL_FILE_RECORD_KEEP_TIME = 21天
RMAN RETENTION POLICY
= RECOVERY WINDOW OF 14 DAYS
全备历史清理
= DELETE OBSOLETE
主库归档
= 3天 + BACKED UP 1 TIMES TO DISK
增加NFS挂载保护
这次问题最值得记录的一点是:
RMAN 备份保留不能只关注磁盘上的 Backup Piece,还必须同时考虑 Control File 中 RMAN Repository 能保存多久。
以后碰到"文件还在,但 RMAN 已经不认识"的问题,优先检查:
V$BACKUP_SET
V$BACKUP_PIECE
V$BACKUP_DATAFILE
CONTROL_FILE_RECORD_KEEP_TIME
RMAN RETENTION POLICY
基本就能快速判断是不是 RMAN Metadata 生命周期导致的问题。