rman不支持“保留10%空间”语法,因其仅按时间、scn或备份状态删除归档,需shell脚本动态计算使用率并调用rman执行;核心是df检测+循环调整completed before时间窗口,配合crosscheck/delete expired释放fra配额。
rman 本身不支持“清理到剩余10%空间”这种动态容量目标,它只能按时间、scn 或备份状态删归档;真正实现“留10%空闲”必须靠 shell 层逻辑控制,rman 只是执行删除的工具。
为什么 RMAN 没有 KEEP SPACE 10% 这类语法
RMAN 的 DELETE ARCHIVELOG 命令只接受明确条件:COMPLETED BEFORE、UNTIL TIME、BACKED UP 2 TIMES TO DEVICE TYPE DISK 等。它不读取文件系统 df -h 输出,也不做容量计算——这是操作系统层的事。
所谓“保留10%”,本质是:先算出归档目录总空间和已用空间,反推“最多能删到多少字节”,再折算成时间边界(比如最近 3 天的归档占 85%,那就要删掉更早的),最后交给 RMAN 执行。
-
control_file_record_keep_time默认仅 7 天(11g),超期归档元数据被覆盖 → RMAN 根本看不见,LIST ARCHIVELOG ALL查不到,CROSSCHECK也扫不到 - 直接用
find -mtime +N -delete风险高:可能误删未应用归档(ADG 环境)、或刚完成但尚未写入控制文件的归档 - 只靠
DELETE ARCHIVELOG ALL COMPLETED BEFORE 'SYSDATE-N'不可靠:归档生成不均匀,某天集中产生大量日志,按固定天数删可能仍剩 30% 占用
shell 脚本中如何动态计算“删到剩10%”
核心思路:用 df 获取归档路径使用率 → 若已用 ≥90%,则逐步扩大 COMPLETED BEFORE 时间窗口,直到 df 显示使用率 ≤90% 或无可再删。
示例关键逻辑(归档路径为 /u01/app/oracle/fast_recovery_area/ORCL/archivelog):
ARCH_DIR="/u01/app/oracle/fast_recovery_area/ORCL/archivelog"
THRESHOLD=90 # 允许最高使用率
<p>used_pct=$(df "$ARCH_DIR" | awk 'NR==2 {print $5}' | sed 's/%//')
if [ "$used_pct" -ge "$THRESHOLD" ]; then</p><h1>从 SYSDATE-3 开始尝试,每轮减1天,最多试到 SYSDATE-30</h1><p>for days in {3..30}; do
$ORACLE_HOME/bin/rman target / </p><h1>检查是否达标</h1><pre class="brush:php;toolbar:false;">new_pct=$(df "$ARCH_DIR" | awk 'NR==2 {print $5}' | sed 's/%//')
if [ "$new_pct" -le "$THRESHOLD" ]; then
echo "✅ 达标:$days 天前归档已清理,当前使用率 $new_pct%"
break
fidone fi
- 必须在
CROSSCHECK后立即执行DELETE EXPIRED,否则旧元数据残留会导致 FRA 配额不释放,df看起来没变化 - 循环里不能用
break后就退出 —— 要加sleep 2,等 RMAN 提交控制文件更新再查df,否则可能读到缓存值 - 若循环跑完仍不达标,说明存在 RMAN 管不到的物理残留(如
control_file_record_keep_time超期文件),需 fallback 到find清理
ADG 备库环境下必须加 applied='YES' 校验
主库删归档看 COMPLETION_TIME 就行,但备库直接删可能引发 GAP —— RMAN 不校验 v$archived_log.applied,只认控制文件记录。脚本里必须先查 SQL:
sqlplus -s / as sysdba
- 拿到最大已应用
SEQUENCE#后,再用LIST ARCHIVELOG FROM SEQUENCE xxx查出对应物理路径,只删这些路径下的文件 - 不能用
COMPLETED BEFORE替代 —— 备库COMPLETION_TIME可能晚于主库,且 MRP 应用有延迟,SYSDATE-7可能刚应用完就被删 - 必须检查
v$archive_gap为空、v$managed_standby.MRP0状态为APPLYING_LOG,否则跳过清理并报错
容易被忽略的三个硬性依赖
脚本跑得通 ≠ 清理有效。以下任一缺失都会导致“看着执行了,空间却不释放”:
-
ORACLE_HOME和ORACLE_SID必须在脚本开头显式export,crontab 中不会自动加载.bash_profile -
control_file_record_keep_time至少设为 30(默认 7),否则超过 7 天的归档永远进不了v$archived_log,RMAN 永远看不见 - 归档路径必须在
db_recovery_file_dest或显式配置的log_archive_dest_n中,否则CROSSCHECK ARCHIVELOG ALL根本不扫描该目录
最隐蔽的问题是:你删的是 FRA 里的归档,但数据库实际往 log_archive_dest_1(比如 /arch)写,RMAN 根本不管那个目录 —— 这时 df 看的是 /arch,而脚本清的是 FRA,完全对不上。











