DELETE EXPIRED BACKUP 返回“0 objects deleted”是因为控制文件中无EXPIRED状态记录,必须先执行CROSSCHECK BACKUPSET ALL、CROSSCHECK COPY ALL和CROSSCHECK ARCHIVELOG ALL等校验命令,使RMAN将实际丢失的备份标记为EXPIRED,之后DELETE EXPIRED才能生效。
为什么 DELETE EXPIRED BACKUP 总是返回 “0 objects deleted”
这不是命令写错了,而是 rman 根本没东西可删——delete expired backup 只清理控制文件里状态已经是 expired 的记录,而这些状态不会自动产生。物理备份文件被 rm、迁移或 fra 自动清理后,控制文件仍长期保留 available 状态,导致后续所有 delete expired 都无效果。
必须先让 RMAN 主动“看一眼磁盘”,把那些实际不存在的备份标记为 EXPIRED,这个动作就是 CROSSCHECK。漏掉这步,等于让 RMAN 对着一张过期地图找车,自然找不到也删不掉。
CROSSCHECK 要覆盖哪些对象才真正有效
只输 CROSSCHECK BACKUP 是生产环境最常见错误:它默认只检查最近一次备份集,大量历史备份集、归档日志、映像副本(COPY)全被跳过。
-
CROSSCHECK BACKUPSET ALL:强制扫描全部备份集,不是“最近一个” -
CROSSCHECK COPY ALL:覆盖所有BACKUP AS COPY或DUPLICATE生成的映像副本 -
CROSSCHECK ARCHIVELOG ALL:关键一步,尤其当归档在 FRA 外独立路径时 - 如果用了恢复目录(recovery catalog),执行完必须补
RESYNC CATALOG,否则主库控制文件和目录元数据不同步,下次CROSSCHECK结果不可信
Data Guard 环境下 CROSSCHECK 容易误标归档
在备库上直接执行 CROSSCHECK ARCHIVELOG ALL 极危险:RMAN 默认按本地 DB_UNIQUE_NAME 匹配,可能把主库刚传过来、尚未应用的归档标为 EXPIRED,导致后续 DELETE EXPIRED ARCHIVELOG 误删,破坏恢复链。
正确做法是:
- 主库操作:直接运行全套
CROSSCHECK命令即可 - 备库操作(仅限必要场景):
CROSSCHECK ARCHIVELOG ALL FOR DB_UNIQUE_NAME <primary_db_name></primary_db_name>,显式限定作用域 - 确认归档应用状态:
SELECT MAX(sequence#), applied FROM v$archived_log GROUP BY applied;,确保待清理归档已APPLIED = 'YES'
删完 EXPIRED 后控制文件里还有残留记录怎么办
执行完 DELETE EXPIRED BACKUP 和 DELETE EXPIRED ARCHIVELOG ALL,LIST BACKUP 仍显示部分条目,或 RC_BACKUP_PIECE 表里有孤立 BP_KEY,这是正常现象——RMAN 不自动清理碎片关联。
安全处理方式是逐项确认,而非强行修改控制文件:
- 对单个疑似丢失的备份集,先用
LIST BACKUPSET <bs_key></bs_key>查HANDLE,再ls -l确认物理路径是否真无文件 - 确认无文件后,用
CHANGE BACKUPSET <bs_key> UNCATALOG</bs_key>显式注销,不走DELETE流程 - 归档日志仍有残留?补一句
CHANGE ARCHIVELOG ALL CROSSCHECK再跑DELETE EXPIRED ARCHIVELOG ALL - 注意:
CROSSCHECK是 I/O 密集型操作,大库建议在业务低峰执行,避免影响归档写入性能
最常被忽略的点是:CROSSCHECK 不是“一次性开关”,而是需要定期嵌入运维脚本的校验环节。哪怕配置了 CONFIGURE ARCHIVELOG DELETION POLICY,只要外部有手动删文件行为,就必须靠它兜底;否则控制文件元数据会持续漂移,最终表现为 FRA 空间“假满”。


















