简介:面向Oracle数据库运维人员与DBA的一份故障处理文档,聚焦归档日志空间占满引发的ORA-00257错误,帮助读者理解该报错的触发背景、常见成因与处置方向。压缩包内仅含1个doc文件,整体约76KB,体量轻便,便于随取随查。文档围绕删除物理日志与登录RMAN释放归档空间两条主线展开,记录了查看空间占用比例、定位日志存放路径、物理清理与逻辑释放之间的衔接,并提示选择性删除、crosscheck标识过期归档等注意事项,可作为日常巡检与应急排障时的对照材料。内容侧重思路梳理与过程留痕,对归档日志机制、空间占用判断、物理文件清理与RMAN逻辑释放之间的配合关系作了串联说明,适合需要快速建立归档日志清理框架、补齐RMAN操作认知的数据库运维人员查阅。目前已有580人学习下载。
1. 归档日志撑爆了:ORA-00257 报错为什么总在凌晨找上门
凌晨两点,数据抽取任务突然停了,应用日志里一行ORA-00257: archiver error. Connect internal only, until freed,接着所有新连接被拒,业务侧电话打过来时你还得先弄明白:这是数据库挂了,还是磁盘满了。这类故障在跑批、抽取、报表链路里太常见了,尤其那种“白天没人动、夜里集中写入”的库,归档日志涨起来是悄无声息的。它折腾人的地方在于:数据库本身没死,SQL 也能连上一部分,但写入和新会话全被卡住,看着像网络问题,其实是归档区满了。这篇排错笔记适合两类人:一是半夜被叫起来救火、只想照着命令一步步恢复业务的同学;二是想搞清楚“为什么删了文件空间还是没释放”的熟手。Oracle 的归档机制本身没问题,问题通常出在空间规划和清理动作的顺序上,下面按现场顺序拆。
2. 报错先定位:三个视图看清是谁把归档区占满了
遇到 ORA-00257,最忌讳的动作是直接上服务器rm文件。先把“占了多少、放在哪、谁在产生”这三件事查清楚,后面每一步才有依据。整个定位过程只用sqlplus和几条查询,不需要额外工具。
2.1 用 v$flash_recovery_area_usage 确认占用比例
以sysdba身份登录后,第一条命令就是看快速恢复区的使用明细,而不是df -h。df只能告诉你磁盘有没有满,但恢复区是有独立配额上限的,磁盘还有空间、恢复区照样能报 00257。
# 切到 oracle 用户,避免用 root 直连数据库 su - oracle # 不走监听,本地直接连,避免监听本身也受影响 sqlplus /nolog进入 SQL 环境后执行:
-- 以 sysdba 身份连接,释放归档必须这个权限 conn / as sysdba -- 查看快速恢复区各类文件的占用比例 select * from v$flash_recovery_area_usage;这条视图返回若干行,重点看FILE_TYPE为ARCHIVED LOG的那一行,两个字段最关键:PERCENT_SPACE_USED是占配额的比例,PERCENT_SPACE_RECLAIMABLE是可回收比例。原料里那次现场是 89.78%,已经逼近上限,抽取任务开始报错。这里有个容易忽略的点:RECLAIMABLE高说明有大量归档已经备份过、按策略可以清,RECLAIMABLE接近 0 才说明是真没得清、得靠加空间或调保留策略。判断“该删还是该扩”,就看这两个数的关系。
顺便把归档模式也确认一下,避免误判:
-- 确认数据库处于归档模式,非归档库不会报这个错 archive log list;2.2 show parameter 查清归档路径和配额上限
知道占满了,下一步是确认“满的是哪个目录、上限是多少”。很多人凭印象去/u01/app/oracle/...找文件,结果删错了目录。
-- 查看恢复区相关参数:路径、配额大小 show parameter recover;这条命令会带出db_recovery_file_dest和db_recovery_file_dest_size两个参数。以原料那次为例,路径是/backup/flash_recovery_area,配额 160G。这两个值决定了你后面该进哪个目录、删多少是安全的。
如果想让输出更清爽,也可以直接查:
-- 只取路径与配额,单位换算成 G 便于判断 select name, value/1024/1024/1024 as size_gb from v$parameter where name in ('db_recovery_file_dest','db_recovery_file_dest_size');参数说明:db_recovery_file_dest是归档与控制文件、备份片的落盘根目录;db_recovery_file_dest_size是逻辑配额,不是磁盘容量。这两个值不一致是常态——磁盘可能有 500G,但配额只给了 160G,那么到 160G 就报错。所以“磁盘没满为什么还报 00257”这个经典疑问,答案就在这里。
2.3 结合告警日志确认报错时间线
定位的最后一步是看告警日志,确认报错前后的动作。归档写失败、清理失败、参数变更都会留痕,时间线对上了,才能排除“其实是备份任务把空间吃掉了”这类误判。
# 告警日志一般在诊断目录下,路径随版本不同,先用 show parameter 确认 sqlplus -S / as sysdba <<'EOF' select value from v$diag_info where name='Diag Trace'; EOF拿到目录后,用tail配合关键字过滤:
# 抓归档相关报错,看首次出现的时间点 grep -iE "ORA-00257|archiv|FRA" alert_*.log | tail -n 50这一步的价值在于区分两种场景:一种是归档正常产生、只是没清理导致堆积;另一种是归档目标本身不可写(目录权限、挂载点异常),后者删文件根本解决不了,得先修路径。原料里的现场属于前者,所以清理动作有效。分不清这两种就动手,很容易白忙一场。
3. 清理要按顺序:删物理文件再用 RMAN 释放逻辑空间
定位清楚之后才轮到动手。这一步是整个故障处理里最容易翻车的地方:Oracle 的归档空间是“物理文件 + 控制文件记录”两套账,只删文件不告诉数据库,空间比例不会下降;只删记录不删文件,磁盘照样满。正确的顺序是先删物理文件,再进 RMAN 做 crosscheck 和 delete expired,把两套账对齐。
3.1 删物理文件:先备份、再选择性删除
进目录之前先做两件事:确认当前没有正在跑的备份任务,确认要删的归档已经备份过。原料里的现场是新库、没有其他操作记录,所以可以整段删;生产库绝对不能这么干。
# 进入归档目录,先看体量和日期分布 du -sh /backup/flash_recovery_area/*/archivelog 2>/dev/null ls -lh /backup/flash_recovery_area/*/archivelog | head -n 20 # 确认没有 rman 备份进程在跑 ps -ef | grep -i rman | grep -v grep确认无误后按日期选择性删除,保留最近若干天的归档,给可能的时间点恢复留余地:
# 删掉指定日期之前的归档文件,保留近 3 天 find /backup/flash_recovery_area -path "*archivelog*" -type f \ -name "*.arc" -mtime +3 -print # 上一条只打印不删,确认清单没问题后,把 -print 换成 -delete find /backup/flash_recovery_area -path "*archivelog*" -type f \ -name "*.arc" -mtime +3 -delete参数说明:-mtime +3表示修改时间在 3 天以前,比手写日期区间稳妥;-path "*archivelog*"限定只碰归档目录,防止误删同级的备份片;先-print再-delete是我一直保留的习惯,多敲一行命令,换一次不后悔。原料里那种rm -rf整目录的写法,只适用于“新库、无其他操作记录”这一种情况,照抄到生产环境是要出事的。
删除完成后,磁盘空间释放了,但数据库还不知道,此时v$flash_recovery_area_usage里的比例可能一点没降,甚至因为控制文件仍记录着这些归档而继续报错。这就是下一步必须进 RMAN 的原因。
3.2 crosscheck:让控制文件认识“文件已经没了”
RMAN 的crosscheck干的事情很朴素:拿控制文件里记录的归档清单,逐个去磁盘上核对,找不到的就标记为EXPIRED。这一步不删任何东西,只改状态,属于安全操作。
# 本地连接,不需要 target 用户名密码 rman target / # 核对所有归档的物理存在性 RMAN> crosscheck archivelog all;执行完会输出一段列表,把刚删掉的文件逐条标为expired。这里要注意两点:一是crosscheck只影响“状态”,不动文件,随时可跑;二是如果归档量很大,这条命令可能跑几分钟,别以为卡死了就 Ctrl+C。原料里的思路正是这个顺序——先删文件、再 crosscheck 标记,最后 delete expired 清账。
如果只想核对某个时间段,避免全量扫描太慢,可以加范围:
# 只核对 7 天前的归档,减少扫描量 RMAN> crosscheck archivelog from time 'sysdate-7';3.3 delete expired:清掉失效记录,空间比例才会回落
crosscheck之后,控制文件里那些归档已经是“失效”状态,但它们仍然占着恢复区的逻辑配额。delete expired就是把这些失效记录从控制文件里摘掉,配额随之释放。
# 删除已被标记为 expired 的归档记录 RMAN> delete expired archivelog all; # 交互确认时输入 YES这一步会要求确认,输入YES回车即可。执行完再回 SQL 环境查比例:
-- 复核释放效果 select * from v$flash_recovery_area_usage;正常情况下ARCHIVED LOG的PERCENT_SPACE_USED会明显下降,业务连接随之恢复,抽取任务重跑即可。如果比例纹丝不动,八成是删的文件和控制文件里记录的根本不是同一批——比如归档路径改过、或者删的是备份片目录,这时候要回到第 2 章重新确认路径。
注意:
delete expired只删“磁盘上已经不存在”的记录;如果文件还在、只是你希望提前清掉,用的是delete archivelog all completed before 'sysdate-3',两者语义完全不同,别用混。
3.4 高频场景:抽取任务卡住时要不要重启实例
很多现场的第一反应是重启数据库,实际上 00257 是“拒绝新的归档写入”,不是实例崩溃,绝大多数情况下清完空间就自行恢复,不需要重启。判断依据是告警日志里有没有伴随的实例异常。
# 清完空间后确认归档写入恢复正常 sqlplus -S / as sysdba <<'EOF' select status, destination, error from v$archive_dest_status where status <> 'INACTIVE'; EOF如果error列为空、状态正常,说明归档链路已经通了,让业务侧重连或重跑任务即可。只有在归档目标本身不可写、参数被改坏的情况下才需要考虑重启或切归档路径,那属于另一类故障,别和空间不足混为一谈。
4. 避坑清单:这几处翻车我见过不止一次
清理归档这件事,命令本身不难,难在几个反直觉的细节。下面五条都是现场真实踩过的,每条按现象、原因、解决写清楚。
4.1 删了文件,占用比例一点没降
现象:rm执行完,df显示磁盘空出来了,但v$flash_recovery_area_usage里归档占用还是 90% 以上,业务继续报错。
原因:Oracle 的恢复区占用是按控制文件里的记录算的,物理文件没了不等于记录没了,配额判断依据的是记录。只删文件等于只撕了账本的一半。
解决:按顺序补跑crosscheck archivelog all;和delete expired archivelog all;,让控制文件认账。之后再查视图确认比例回落,别只看磁盘。
4.2 crosscheck 报错找不到文件,命令直接中断
现象:运行crosscheck时输出一堆ORA-19625之类的错误,提示无法获取文件状态。
原因:文件已经被删除,RMAN 去读文件头自然失败;如果删除时还带着目录一起删,路径都不存在,报错更密集。
解决:这类报错是预期内的,crosscheck的作用就是把它们标成expired,命令跑完继续执行delete expired即可。如果报的是权限或挂载点问题,那才是真异常,要先修路径。
4.3 全量删除导致无法做时间点恢复
现象:空间是清出来了,几天后业务要求恢复到某个历史时间点,发现归档缺失,恢复链断了。
原因:把归档目录整段清空,等于把可恢复性一起删了。原料里明确说了这是新库、没有其他操作记录,才敢全删;生产库照做就是事故。
解决:按保留策略选择性删除,用-mtime控制保留天数,且删除前确认这批归档已有备份。归档的核心价值就是可恢复性,清空间不能以牺牲它为代价。
4.4 配额没调,清完几天又报同样的错
现象:清理后恢复正常,过三五天同样的 ORA-00257 再来一次,成了周期性故障。
原因:只做了“清”,没做“防”。归档产生速度和保留策略不匹配,配额又偏小,清完必然再堆满。
解决:两手一起做。短期把db_recovery_file_dest_size调到与磁盘容量匹配的合理值;长期配置归档删除策略,让 RMAN 按保留窗口自动清理,不再依赖人工救火。
-- 调整恢复区配额,需 sysdba 权限,动态生效 alter system set db_recovery_file_dest_size = 300G;参数说明:这个值是逻辑上限,不要超过所在文件系统的实际可用空间,否则配额还没到、磁盘先满,问题更难查。改完用show parameter recover复核。
4.5 在业务高峰期做清理,锁等待把任务拖死
现象:清理过程中业务 SQL 大面积变慢,出现大量enq: CF相关等待。
原因:crosscheck和delete expired会短时持有控制文件相关资源,归档量大时扫描时间长,高峰期执行影响明显。
解决:把清理动作放到低峰窗口,或者分批做——先crosscheck一段时间的归档,再删除,缩小单次扫描范围。应急场景下优先恢复业务,清理可以分多次完成。
5. 快速定位:把这次救火变成下次的三分钟
处理过一次之后,我更关心的不是“这次怎么修好的”,而是下次再报同样的错,能不能在三分钟内判断出属于哪一类、该走哪条路。归档类故障的定位其实可以收敛成一套固定动作,顺序别乱,判断依据就那么几个数。
第一步永远是看比例而不是看磁盘。连上库先跑select * from v$flash_recovery_area_usage;,ARCHIVED LOG行的PERCENT_SPACE_USED和PERCENT_SPACE_RECLAIMABLE两个数一出来,方向基本就定了:
| 现象组合 | 大概率原因 | 处理方向 |
|---|---|---|
| 占用高、可回收也高 | 归档堆积未清理 | 删文件 + crosscheck + delete expired |
| 占用高、可回收接近 0 | 归档都未备份或保留策略过长 | 先备份,再调保留策略 |
| 占用不高却仍报 00257 | 归档目标不可写或参数异常 | 查v$archive_dest_status的 error 列 |
| 清理后比例不降 | 只删了文件没清记录 | 补跑 RMAN 两条命令 |
第二步确认路径与配额,show parameter recover一条命令拿到db_recovery_file_dest和db_recovery_file_dest_size,和自己以为的目录对一遍,这一步能挡掉大部分“删错地方”的低级失误。第三步才动手,而且动手前一定先-print看清单。
有个验证习惯值得固定下来:清理完成后不要只看视图,还要确认归档写入真的恢复了。
# 清理后的三步复核:比例、归档状态、新归档是否正常产生 sqlplus -S / as sysdba <<'EOF' select file_type, percent_space_used, percent_space_reclaimable from v$flash_recovery_area_usage where file_type='ARCHIVED LOG'; select status, error from v$archive_dest_status where status <> 'INACTIVE'; archive log list; EOF三项都正常,才算这次真的收尾,而不是把问题往后推了几天。这份文档把现场的两步核心动作——删物理文件、登录 RMAN 释放空间——连同查询语句和路径参数都记了下来,照着走一遍就能复现整条处理链路,适合放在手边当应急手册用。
从那以后我每次碰归档相关操作,都强制自己先跑一遍v$flash_recovery_area_usage,再决定动不动手;删文件前必-print一遍清单,清完必查三项复核。血泪经验就一句话:Oracle 的归档是两套账,只平一套,另一套迟早来找你。希望帮到你。
本文还有配套的精品资源,点击获取