一、问题背景
在 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 生命周期导致的问题。
以上就是oracle 19c rman历史备份清理失败问题排查与整改实战的详细内容,更多关于oracle 19c rman历史备份清理失败的资料请关注代码网其它相关文章!
发表评论