简介:这份文档面向 Oracle 数据库运维与 DBA 人员,聚焦归档日志写满引发的 ORA-00257 报错,提供一套可落地的处理思路与操作记录。内容围绕 Archivelog 机制展开,先说明该错误产生的原理,再给出「删除物理文件 + 登录 RMAN 释放逻辑空间」两条主线,并附上查看归档占用比例、确认日志存放路径、crosscheck 与 delete expired 等关键命令的实际执行过程,同时提醒选择性删除日志、避免影响数据库可恢复性等注意事项。资源包共 1 个 doc 文件,约 76KB,属于纯文档型资料,便于随时查阅与对照操作。目前已有 579 人学习,适合遇到归档空间告警、需要快速排错并恢复数据库正常运行的运维人员参考,也可作为日常巡检与应急处理的流程备忘。
1. ORA-00257 报错那一刻:数据抽取任务为什么突然停了
凌晨两点,数据抽取任务突然停了,日志里只有一行冷冰冰的ORA-00257: archiver error. Connect internal only, until freed。这不是数据库崩了,而是 Oracle 的归档日志把闪回恢复区撑满了。归档日志(archivelog)是数据库为了可恢复性记录的所有变更,一旦db_recovery_file_dest_size配额被占满,Oracle 就会拒绝新的归档写入,连带所有依赖归档的操作全部挂起。这份文档记录的正是我处理这类故障的完整思路:先删物理文件,再进 RMAN 释放逻辑空间。适合每天跟 Oracle 打交道的 DBA 和运维,尤其是那些被rman备份老是满折磨过的同行。下面把每一步拆开,参数、命令、坑点都摆出来。
2. 先看清空间去哪了:v$flash_recovery_area_usage 与 recover 参数
处理 ORA-00257 最忌讳上来就删文件。你得先确认两件事:归档日志到底占了多少、恢复区配额设了多大。Oracle 提供了两个视图和参数,一个看占用比例,一个看路径和上限。搞清楚这两个数,后面删多少、删哪里才有依据。
2.1 用 v$flash_recovery_area_usage 定位占用比例
登录数据库后第一件事不是删,是查。v$flash_recovery_area_usage这个视图会按文件类型列出恢复区的使用百分比,其中ARCHIVED LOG那一行就是归档日志的占用。文档里查到的是 89.78%,这个数字一旦逼近 100%,数据抽取任务就会停。查询命令如下:
-- 切换到 oracle 用户后登录数据库 -- su - oracle -- sqlplus /nolog SQL> conn /as sysdba SQL> select * from v$flash_recovery_area_usage;执行后会看到类似ARCHIVED LOG | 89.78 | ...的输出。PERCENT_SPACE_USED列就是占用比例,PERCENT_SPACE_RECLAIMABLE列表示可通过删除过期归档回收的比例。如果RECLAIMABLE很高但USED也高,说明有大量已失效的归档没被清理,这正是 RMANcrosscheck要解决的问题。注意,这个视图查的是逻辑配额,不是物理磁盘的df -h,两者可能不一致,因为恢复区大小由参数控制。
2.2 show parameter recover 确认路径与配额上限
知道占用比例后,得确认归档到底写在哪个目录、配额给了多少。show parameter recover会列出db_recovery_file_dest和db_recovery_file_dest_size两个关键参数。文档里路径是/backup/flash_recovery_area,大小 160G。命令和输出解读如下:
SQL> show parameter recover;输出中db_recovery_file_dest是归档存放的根目录,db_recovery_file_dest_size是恢复区能用的最大空间。常见做法是把这个值设成磁盘实际可用空间的 80% 左右,留出余量。如果这个值设得比磁盘实际空间还大,Oracle 会以为还能写,直到操作系统层面写不进去才报错,那时候排查就更绕。我一般会同时开一个终端跑df -h /backup对照看,确认物理磁盘没满。两个数都清楚了,再决定删哪些、删多少。
3. 删物理文件与 RMAN 释放:两条命令链的配合
ORA-00257 的处理分两个层面:操作系统层面删掉物理归档文件,数据库层面让 RMAN 知道这些文件没了并释放逻辑空间。只删物理文件不跑 RMAN,恢复区占用比例不会降,因为 Oracle 元数据里还记着这些文件。只跑 RMAN 不删物理文件,空间也释放不出来。两条链必须配合。
3.1 选择性删除物理归档文件
登录 Oracle 服务器,切到 oracle 用户,进入归档路径。文档里的路径是/backup/flash_recovery_area,下面按日期分了2012_06_10、2012_06_11这样的目录。删除时要选择性删,不要rm -rf整个 archivelog 目录。文档里因为是新库没有其他操作记录才全删,生产库绝对不能这么干。操作如下:
# 切换到 oracle 用户 su - oracle # 查看归档目录结构,确认日期目录 ls -l /backup/flash_recovery_area/*/archivelog/ # 选择性删除较早的日期目录,保留最近的 rm -rf /backup/flash_recovery_area/*/archivelog/2012_06_10rm -rf后面跟的是具体日期目录,不是整个archivelog。删之前用ls确认目录内容,删之后再用ls确认文件确实没了。这里有个血泪经验:如果数据库还在运行且归档目标没改,删掉的目录可能马上被新归档重新创建,所以删完要尽快进 RMAN 做crosscheck,否则新归档又写进来,占用比例降不下去。另外,删除操作最好在业务低峰期做,避免正在进行的备份或抽取任务读到不存在的归档文件而报错。
3.2 crosscheck 与 delete expired 释放逻辑空间
物理文件删完后,进 RMAN 执行crosscheck archivelog all。这条命令会扫描恢复区,把物理上已经不存在的归档在控制文件中标记为EXPIRED。注意,crosscheck只是标记,不删除记录,也不释放空间。真正释放空间的是delete expired archivelog all。命令序列如下:
# 登录 RMAN rman target / # 检查所有归档,将物理不存在的标记为 expired RMAN> crosscheck archivelog all; # 删除已标记为 expired 的归档记录,释放恢复区空间 RMAN> delete expired archivelog all;执行delete expired时会提示确认,输入YES即可。完成后回到 SQLPlus 再查一次v$flash_recovery_area_usage,ARCHIVED LOG的占用比例应该明显下降。这里有个参数细节:crosscheck archivelog all会检查所有归档,如果归档量很大,执行时间可能较长,可以加channel并行,但单实例库一般不需要。另外,delete expired只删控制文件里标记为 expired 的记录,不会碰物理文件,所以顺序不能反——先删物理文件,再crosscheck,再delete expired。如果先delete expired再删物理文件,控制文件里记录没了,物理文件还在,空间照样占着。
4. 避坑与排查:ORA-00257 处理中的五个常见翻车点
这套流程看着简单,但实际操作里翻车的地方不少。下面五条是我和同行踩过的坑,每条按现象、原因、解决写清楚。
4.1 删完物理文件,占用比例纹丝不动
现象:rm -rf执行完,ls确认文件没了,但v$flash_recovery_area_usage里ARCHIVED LOG还是 89%。原因:只删了物理文件,没跑 RMANcrosscheck和delete expired,Oracle 控制文件里还记着这些归档,逻辑空间没释放。解决:按顺序执行crosscheck archivelog all和delete expired archivelog all,再查视图确认。
4.2 crosscheck 报 ORA-08186 或文件不存在
现象:crosscheck archivelog all执行时报ORA-08186: invalid timestamp或提示文件不存在。原因:物理文件已经删了,但控制文件里的记录还在,crosscheck找不到文件就会报这个。这其实是正常现象,crosscheck的目的就是把它们标记为 expired。解决:忽略这个提示,继续执行delete expired archivelog all。如果报错导致crosscheck中断,可以加crosscheck archivelog all后跟delete expired archivelog all一起跑。
4.3 删除了还在备份集里的归档
现象:删完归档后,RMAN 备份任务失败,提示找不到归档日志。原因:删掉的归档文件被某个备份集或 Data Guard 依赖,物理删除后备份链断了。解决:删之前用list archivelog all确认哪些归档还被需要,或者用delete archivelog until time 'sysdate-7'这种带条件的 RMAN 删除,而不是直接rm。生产库建议保留最近 7 天归档,删更早的。
4.4 恢复区配额设得比磁盘实际空间大
现象:db_recovery_file_dest_size设了 160G,但/backup分区实际只有 100G,归档写到 100G 时操作系统报磁盘满,Oracle 却还没报 ORA-00257。原因:Oracle 按参数配额判断,不直接感知磁盘物理上限。解决:把db_recovery_file_dest_size设成磁盘实际可用空间的 80% 左右,并定期用df -h对照。修改命令:alter system set db_recovery_file_dest_size=120G scope=both;。
4.5 归档删除后新归档立刻又写满
现象:刚释放完空间,没过多久 ORA-00257 又来了。原因:归档产生速度太快,或者归档删除策略没配,只靠手动删治标不治本。解决:配置 RMAN 自动删除策略,比如configure retention policy to recovery window of 7 days;,再配一个定时任务跑delete obsolete。另外检查log_archive_dest是否指向了正确的恢复区,避免归档写到别处又占满另一个分区。
5. 进阶:用 RMAN 保留策略替代手动删除
手动删物理文件加crosscheck能救急,但不是长久之计。真正稳的做法是配 RMAN 保留策略,让 Oracle 自己管归档的生命周期。我现在的习惯是:新库上线第一件事就是配retention policy,然后每天定时跑delete obsolete,再也没被 ORA-00257 半夜叫醒过。
5.1 配置保留策略与自动删除
RMAN 的保留策略有两种:按恢复窗口(recovery window)和按冗余份数(redundancy)。按恢复窗口更直观,比如保留 7 天,意思是能恢复到过去 7 天内任意时间点。配置命令如下:
rman target / # 配置保留策略为 7 天恢复窗口 RMAN> configure retention policy to recovery window of 7 days; # 查看当前策略 RMAN> show retention policy; # 手动执行一次删除过期归档 RMAN> delete obsolete;delete obsolete会根据保留策略判断哪些归档不再需要,然后删除物理文件和控制文件记录。注意,obsolete和expired是两回事:expired是物理文件没了但记录还在,obsolete是按策略不再需要的。两者可以一起用:先crosscheck标记 expired,再delete expired清理记录,最后delete obsolete按策略删多余归档。
5.2 用 until time 精确控制删除范围
有时候不想全删,只想删某个时间点之前的归档。RMAN 的delete archivelog until time比rm精确得多,而且会同步更新控制文件。常用命令对比:
| 命令 | 作用 | 适用场景 |
|---|---|---|
delete archivelog until time 'sysdate-7' | 删除 7 天前的归档 | 日常清理 |
delete archivelog until sequence 1000 | 删除序列号 1000 之前的归档 | 按序列精确控制 |
delete archivelog all completed before 'sysdate-1' | 删除 1 天前完成的归档 | 配合备份窗口 |
crosscheck archivelog all | 标记物理不存在的归档 | 物理文件已删后 |
这些命令执行前建议先跑list archivelog until time 'sysdate-7'看会删哪些,确认无误再执行delete。我一般会先list再delete,这个习惯救过我好几次——有一次sysdate-7写成了sysdate-70,list一看要删 70 天的归档,赶紧改回来。
5.3 验证释放效果与日常巡检
配完策略后,验证方法很简单:查v$flash_recovery_area_usage看ARCHIVED LOG占用是否稳定在低位,再查v$archived_log确认归档记录数和时间范围符合预期。日常巡检我会跑这几条:
-- 查看恢复区占用 select * from v$flash_recovery_area_usage; -- 查看归档日志数量和最早最晚时间 select count(*), min(first_time), max(first_time) from v$archived_log; -- 查看恢复区参数 show parameter db_recovery_file_dest;如果PERCENT_SPACE_USED持续高于 70%,就该检查保留策略是不是太宽松,或者归档产生速度是不是异常。另外,v$archived_log里DELETED列为YES的记录如果很多,说明crosscheck后没及时delete expired,逻辑空间没释放干净。
从那以后我每次处理 ORA-00257 都强制走一遍「查视图 → 看参数 → 删物理 → crosscheck → delete expired → 复查」的流程,再也没出现过删了文件空间不释放的玄学问题。希望帮到你。
本文还有配套的精品资源,点击获取