简介这份文档面向 Oracle 数据库运维与 DBA 人员聚焦归档日志写满导致的 ORA-00257 报错提供一套可落地的处理思路与操作记录。资源包共 1 个 doc 文件大小约 76KB内容围绕删除物理日志文件与登录 RMAN 释放归档空间两条主线展开涵盖查看 flash recovery area 占用比例、确认日志存放路径与空间大小、选择性清理归档文件、执行 crosscheck 与 delete expired 等关键环节并附有操作提示与注意事项。目前已有 579 人学习浏览适合正在排查归档空间告警、需要快速恢复数据库写入的运维人员参考。读者可借此掌握从定位占用到释放空间的完整排错路径理解物理删除与逻辑释放的配合方式避免因误删全部日志而影响数据库可恢复性也可作为日常巡检与应急处理的对照材料。1. ORA-00257 不是磁盘满是归档日志把恢复区撑爆了凌晨两点监控告警炸了业务库连不上应用日志里清一色ORA-00257: archiver error. Connect internal only, until freed。第一反应是磁盘满了登上去df -h一看根分区还有 40% 空闲可归档目录所在的挂载点已经 100%。这就是 ORA-00257 最典型的现场——不是整个磁盘满是FRAFast Recovery Area快速恢复区或归档目标路径被 archivelog 塞满了。Oracle 在归档写不进去时会挂起所有前台进程只留sysdba能连业务直接停摆。这个错误背后牵扯三件事归档日志为什么会堆积、RMAN 的删除策略怎么配、以及出事后怎么在不丢数据的前提下把空间抢回来。适合正在管 Oracle 单实例或 RAC 的 DBA、运维也适合被rman 备份老是满折磨过的开发。下面按“先止血、再治本、最后防复发”的顺序讲透命令都能直接抄。2. 先搞懂 ORA-00257 的触发链路归档、FRA 与 RMAN 保留策略2.1 归档日志写不进去时Oracle 到底做了什么Oracle 在ARCHIVELOG模式下每次日志切换log switch都会把在线重做日志复制成归档日志。归档目标由两个参数决定LOG_ARCHIVE_DEST_n指定路径DB_RECOVERY_FILE_DEST指定 FRA。如果两者都指向 FRA归档日志、控制文件自动备份、闪回日志全挤在同一个空间里。当 FRA 使用率达到DB_RECOVERY_FILE_DEST_SIZE设定的上限或者物理磁盘真的写满归档进程ARCn就会报错。此时 Oracle 的行为很“硬”所有需要写 redo 的会话被挂起只有SYSDBA能登录。这就是为什么应用报的是连接失败而不是“磁盘满”——错误被 Oracle 拦在了归档层。关键参数就三个参数作用典型值DB_RECOVERY_FILE_DESTFRA 路径/u01/app/oracle/fast_recovery_areaDB_RECOVERY_FILE_DEST_SIZEFRA 逻辑上限根据磁盘规划常见 100G~500GLOG_ARCHIVE_DEST_1归档目标LOCATIONUSE_DB_RECOVERY_FILE_DEST很多人只盯着物理磁盘忘了DB_RECOVERY_FILE_DEST_SIZE是个逻辑配额。磁盘还有空间但配额到了照样报 ORA-00257。这是第一个高频误判点。2.2 为什么 RMAN 备份“老是满”保留策略没配对rman 备份老是满这个热搜词背后十有八九是保留策略retention policy和删除命令没配合好。RMAN 的保留策略有两种基于恢复窗口CONFIGURE RETENTION POLICY TO RECOVERY WINDOW OF 7 DAYS;表示保证能恢复到 7 天内任意时间点超过的才标记为 obsolete。基于冗余份数CONFIGURE RETENTION POLICY TO REDUNDANCY 2;表示每份数据保留 2 个备份。问题在于RMAN 不会自动删除归档日志除非你显式执行DELETE ARCHIVELOG或DELETE OBSOLETE。备份任务每天跑归档每天产生但删除任务没配FRA 只进不出迟早爆。另一个坑是DELETE OBSOLETE只删“过期备份”归档日志如果没被纳入保留策略计算它不碰。所以治本的第一步是让归档日志的删除和备份策略联动。常见做法是备份完成后立刻执行DELETE ARCHIVELOG ALL COMPLETED BEFORE SYSDATE-1或者用DELETE OBSOLETE配合ARCHIVELOG DELETION POLICY。后者更规范-- 配置归档删除策略只有备份到磁盘并成功后才允许删除归档 CONFIGURE ARCHIVELOG DELETION POLICY TO BACKED UP 1 TIMES TO DISK;这条配置的意思是归档日志必须至少被备份过一次到磁盘才允许被删除。它防止“还没备份就把归档删了结果无法恢复”的灾难。配好之后DELETE OBSOLETE才会安全地清理归档。2.3 止血第一步不丢数据的空间回收顺序已经报 ORA-00257 了业务挂着这时候不能慌。回收顺序错了可能把唯一可用的归档删掉导致数据库无法恢复。我一般按这个顺序操作确认归档路径和 FRA 使用率SELECT * FROM V$RECOVERY_FILE_DEST;看SPACE_USED和SPACE_LIMIT。查归档日志列表SELECT * FROM V$ARCHIVED_LOG ORDER BY FIRST_TIME;确认哪些已经备份过。先备份再删除如果还有空间写备份立刻BACKUP ARCHIVELOG ALL;然后DELETE ARCHIVELOG ALL COMPLETED BEFORE SYSDATE-1;。实在没空间写备份只能先DELETE ARCHIVELOG ALL COMPLETED BEFORE SYSDATE-2;赌最近两天的归档还在在线日志或已有备份里。这是下策但业务停摆时不得不做。注意DELETE ARCHIVELOG删除的是物理文件删除前务必确认这些归档已经备份或者数据库处于可接受丢失的窗口内。生产库上这一步最好有变更评审。止血之后ALTER SYSTEM ARCHIVE LOG CURRENT;触发一次归档看 ARCn 是否恢复。如果还是报错检查DB_RECOVERY_FILE_DEST_SIZE是不是设得太小临时调大ALTER SYSTEM SET DB_RECOVERY_FILE_DEST_SIZE 200G SCOPEBOTH;这个命令立即生效不需要重启。调大之后Oracle 会重新尝试归档业务通常几十秒内恢复。3. 用 RMAN 把归档清理做成自动化命令、脚本与参数3.1DELETE ARCHIVELOG的BEFORE、UNTIL、FROM到底怎么选热搜里rman delete archive from until before 区别问得很多这三个词确实容易混。直接给结论BEFORE SYSDATE-1删除完成时间早于指定时间点的归档。最常用按时间窗口清理。UNTIL SYSDATE-1删除截止到指定时间点的归档语义和BEFORE接近但UNTIL更强调“到这个点为止”在DELETE命令里两者行为基本一致官方文档也常混用。FROM ... TO ...指定一个时间区间删除区间内的归档。比如FROM SYSDATE-7 TO SYSDATE-3删 7 天前到 3 天前的。实际脚本里我几乎只用BEFORE因为语义最清晰保留最近 N 天删更早的。FROM ... TO ...适合做精细清理比如只删某个历史区间但日常自动化没必要。一个完整的清理脚本长这样#!/bin/bash # rman_clean_arch.sh - 清理已备份的归档日志 export ORACLE_SIDorcl export ORACLE_HOME/u01/app/oracle/product/19.0.0/dbhome_1 export PATH$ORACLE_HOME/bin:$PATH rman target / log/tmp/rman_clean_$$.log EOF CONFIGURE ARCHIVELOG DELETION POLICY TO BACKED UP 1 TIMES TO DISK; CROSSCHECK ARCHIVELOG ALL; DELETE EXPIRED ARCHIVELOG ALL; DELETE ARCHIVELOG ALL COMPLETED BEFORE SYSDATE-2; DELETE OBSOLETE; EXIT; EOF # 检查日志中是否有错误 if grep -q RMAN- /tmp/rman_clean_$$.log; then echo RMAN清理出现错误请检查 /tmp/rman_clean_$$.log exit 1 fi echo 归档清理完成逻辑说明CROSSCHECK先核对物理文件和 RMAN 仓库记录把已经不存在的标记为 expiredDELETE EXPIRED清掉这些失效记录DELETE ARCHIVELOG ... BEFORE SYSDATE-2删除两天前且已备份的归档DELETE OBSOLETE清理过期备份集。参数SYSDATE-2可以根据备份频率调整如果每天全备保留 1 天也够如果增量备份间隔长保留 3~7 天更稳。3.2 把清理挂到 crontab时间窗口和并发控制清理脚本不能和备份脚本同时跑否则可能删掉正在备份的归档。常见做法是备份完成后触发清理或者错开时间。用 crontab 的话# 每天凌晨 2 点全备4 点清理归档 0 2 * * * /home/oracle/scripts/rman_backup.sh /home/oracle/logs/backup.log 21 0 4 * * * /home/oracle/scripts/rman_clean_arch.sh /home/oracle/logs/clean.log 21如果备份时间不确定可以在清理脚本开头加一个检查确认没有正在运行的 RMAN 备份进程。# 检查是否有正在运行的 RMAN 进程 if pgrep -f rman target /dev/null; then echo RMAN 正在运行跳过本次清理 exit 0 fi这个检查很粗糙但能挡住大部分并发冲突。更严谨的做法是用 Oracle 的V$RMAN_STATUS视图查RUNNING状态不过脚本里连数据库查会增加复杂度按需选择。3.3 用DB_RECOVERY_FILE_DEST_SIZE做预警而不是等报错ORA-00257 最恶心的地方是它直接挂业务。与其等它报错不如提前预警。FRA 使用率超过 80% 就该关注超过 90% 必须处理。查使用率SELECT name, ROUND(space_limit / 1024 / 1024 / 1024, 2) AS limit_gb, ROUND(space_used / 1024 / 1024 / 1024, 2) AS used_gb, ROUND(space_used / space_limit * 100, 2) AS used_pct FROM V$RECOVERY_FILE_DEST;把这个查询塞进监控系统阈值设 85%比等 ORA-00257 告警主动得多。另一个指标是V$ARCHIVED_LOG里未备份的归档数量SELECT COUNT(*) AS unbacked_archives FROM V$ARCHIVED_LOG WHERE BACKUP_COUNT 0 AND DELETED NO;BACKUP_COUNT 0表示还没被备份过。这个数持续增长说明备份任务可能失败了或者归档删除策略没生效。两个指标一起看基本能提前 1~2 天发现隐患。4. 避坑与排查ORA-00257 处理中的 5 个血泪教训4.1 坑一只扩磁盘没调DB_RECOVERY_FILE_DEST_SIZE现象df -h看磁盘还有空间但 ORA-00257 依旧。原因FRA 的逻辑配额DB_RECOVERY_FILE_DEST_SIZE到了Oracle 不管物理磁盘还剩多少直接拒绝写归档。解决ALTER SYSTEM SET DB_RECOVERY_FILE_DEST_SIZE 新值 SCOPEBOTH;立即生效。扩物理磁盘是另一回事逻辑配额必须先放开。4.2 坑二DELETE ARCHIVELOG ALL不带条件把没备份的删了现象清理完空间业务恢复了但后来想恢复某个时间点发现归档缺失RMAN 报RMAN-06025。原因执行了DELETE ARCHIVELOG ALL;没加BEFORE条件把所有归档包括未备份的全删了。解决永远带BEFORE SYSDATE-N并且先配ARCHIVELOG DELETION POLICY TO BACKED UP 1 TIMES TO DISK。删除前用LIST ARCHIVELOG ALL;确认哪些已备份。4.3 坑三备份任务失败但没人发现归档只进不出现象FRA 使用率每天涨 5%一周后爆。查备份日志发现三天前就报错了。原因备份脚本失败没有告警crontab 默默执行归档清理依赖备份成功备份挂了清理也挂。解决备份脚本里加错误检查失败时发邮件或写系统日志。上面 3.1 的脚本里grep RMAN-就是干这个的。监控系统里对V$ARCHIVED_LOG.BACKUP_COUNT 0的数量设阈值。4.4 坑四RAC 环境下只清理了一个节点现象RAC 两个节点节点 1 的归档目录空了节点 2 的还满着ORA-00257 依旧。原因RAC 每个实例有独立的归档目标如果没配共享存储RMAN 连接一个实例只能清理它看到的归档。解决RAC 下用CONFIGURE ARCHIVELOG DELETION POLICY配全局策略或者分别连每个实例执行清理。更稳的做法是把归档放在共享存储上RMAN 通过扫描全部归档来清理。4.5 坑五CROSSCHECK没跑就DELETE EXPIRED删了个寂寞现象执行DELETE EXPIRED ARCHIVELOG ALL;后FRA 使用率没降。原因DELETE EXPIRED只删除 RMAN 仓库里标记为 expired 的记录而 expired 状态需要CROSSCHECK先核对物理文件是否存在。没跑CROSSCHECK所有归档都是 available 状态DELETE EXPIRED什么都不删。解决顺序固定为CROSSCHECK ARCHIVELOG ALL;→DELETE EXPIRED ARCHIVELOG ALL;→DELETE ARCHIVELOG ... BEFORE ...;。三步缺一不可。5. 进阶用DELETE OBSOLETE 恢复窗口做“按分钟回退”的归档管理rman 备份 按分钟回退这个需求本质是要求恢复窗口精确到分钟级。RMAN 的RECOVERY WINDOW支持小数天比如RECOVERY WINDOW OF 0.5 DAYS就是 12 小时。但归档日志的删除不能只看恢复窗口还要看备份是否完成。一个可落地的精细策略-- 恢复窗口设为 12 小时保证半天内任意时间点可恢复 CONFIGURE RETENTION POLICY TO RECOVERY WINDOW OF 0.5 DAYS; -- 归档删除策略备份到磁盘 1 次后才允许删 CONFIGURE ARCHIVELOG DELETION POLICY TO BACKED UP 1 TIMES TO DISK; -- 每天两次全备间隔 12 小时 -- 备份后执行 DELETE OBSOLETERMAN 会自动计算哪些归档超出恢复窗口这里的关键是DELETE OBSOLETE和RECOVERY WINDOW的联动。RMAN 会根据恢复窗口计算“最早需要的归档时间点”然后删除比这个时间点更早的、且已备份的归档。比如现在是 14:00恢复窗口 0.5 天那么 02:00 之前的归档如果已备份就会被标记为 obsolete。验证方法执行REPORT OBSOLETE;看哪些归档会被删确认无误再DELETE OBSOLETE;。这个命令是“后悔药”删之前先看一眼。-- 先报告不删除 REPORT OBSOLETE; -- 确认列表无误后执行删除 DELETE OBSOLETE;我一般会在清理脚本里先跑REPORT OBSOLETE把结果写日志再跑DELETE OBSOLETE。这样出问题能回溯当时删了哪些。另一个习惯是每次调整RETENTION POLICY或ARCHIVELOG DELETION POLICY后手动跑一次REPORT OBSOLETE确认新策略符合预期再交给自动化。最后说个我自己的教训早年管的一个库FRA 设了 500G觉得够大结果归档每天 80G一周就爆。后来把DB_RECOVERY_FILE_DEST_SIZE调到 1T同时上了清理脚本和监控再没出过 ORA-00257。空间给够是基础但自动化清理和预警才是保命的。希望帮到你。本文还有配套的精品资源点击获取