马上注册,结交更多好友,享用更多功能,让你轻松玩转社区。
您需要 登录 才可以下载或查看,没有账号?用户注册
×
Oracle 归档日志空间治理实战:从 ORA-00257 到闪回区规划
一、具体的问题
早上八点,业务方反馈系统报「ORA-00257: archiver error. Connect internal only, until freed」,新连接登不上,已有会话的 INSERT/UPDATE 也全部卡住。你远程登上去 df -h 一看,磁盘还有 200G 空闲,alert.log 里却刷满了 ORA-19815: WARNING: db_recovery_file_dest_size of 53687091200 bytes is 100.00% used——磁盘没满,数据库却说写不了日志。这是 DBA 最常见也最冤枉的一种「假故障」:明明备份文件一堆堆躺在那里,真正的原因是闪回区(FRA)的配额被吃光了,而不是磁盘被吃光。处理不好,轻则数据库写操作挂几十分钟,重则有人在慌乱中直接 rm 归档文件,把恢复链彻底断掉。本文把这类事故的排查、止血、根治一次讲透。
二、核心原理
要理解 ORA-00257 的机制,得先分清三样东西:磁盘空间、归档目的地、配额。
Oracle 11g 之后,归档日志默认写入闪回区(Fast Recovery Area),由 db_recovery_file_dest 指定目录、db_recovery_file_dest_size 指定逻辑配额。这个配额是 Oracle 自己记账的软上限,跟操作系统磁盘大小是两回事——磁盘 500G、配额 50G,配额先用完照样报错。FRA 里躺着归档日志、备份集、镜像副本、闪回日志、控制文件自动备份等多类文件,v$flash_recovery_area_usage 能看到每类占了多少。
FRA 满之后,归档进程 ARCn 无法写新的归档文件,日志切换完成不了,所有产生 redo 的 DML 都会挂起——这就是为什么存量会话也卡住。而「卡住」的根因,十有八九不是归档来得太快,而是旧归档一直没人删:RMAN 备份任务连续失败三天没被发现,或者备份脚本只备份不删除,归档文件越积越多,配额迟早见底。
这里最容易犯的致命错误是用操作系统命令 rm 删归档文件。FRA 的空间记账在控制文件和 RMAN 仓库里,rm 删掉的是物理文件,账本上这些文件还在,v$recovery_file_dest 统计的 SPACE_USED 不会下降,配额照样是满的——人吓一身冷汗,问题一个没解决。清理归档必须走 RMAN,让删除动作同步登记回控制文件,SPACE_RECLAIMABLE 才会变成可用空间。
还有一条约束必须记住:归档日志是时间点恢复的原料,删之前必须确认它已经被备份过;有 Data Guard 的环境,还要确认备库已经 apply,否则删多了会造成备库 gap 或者恢复窗口缺口。
三、实例参考(动手步骤)
步骤 0:确认现状基线
- -- FRA 配额与用量:看 SPACE_LIMIT / SPACE_USED / SPACE_RECLAIMABLE
- SELECT name, space_limit/1024/1024 AS limit_mb,
- space_used/1024/1024 AS used_mb,
- space_reclaimable/1024/1024 AS reclaim_mb,
- number_of_files
- FROM v$recovery_file_dest;
- -- 分类型看占用:归档占了多少、哪些可回收
- SELECT file_type, percent_space_used, percent_space_reclaimable
- FROM v$flash_recovery_area_usage ORDER BY percent_space_used DESC;
复制代码- # 对比操作系统侧:磁盘还有余量,说明是配额问题而非磁盘问题
- df -h /u01/fast_recovery_area
- grep -E "ORA-19815|ORA-00257|ORA-19809" $ORACLE_BASE/diag/rdbms/*/trace/alert_*.log | tail -20
复制代码
如果 percent_space_used 里 ARCHIVED LOG 一项 90% 以上而 percent_space_reclaimable 接近 0,说明归档既多又没被登记为「可回收」——即没做过备份或 crosscheck。
步骤 1:止血——先把配额抬上去
确认磁盘真实有富余后,先在线扩配额让业务恢复,这一步秒级生效、无需重启:
- ALTER SYSTEM SET db_recovery_file_dest_size = 80G SCOPE=BOTH;
复制代码
注意这是止血不是治疗:如果根因是备份任务断了,配额抬得再高也只是延缓爆掉的时间。止血窗口内立刻做步骤 2。
步骤 2:RMAN 清理旧归档
- -- 1) 校对账本:把已被 OS 误删文件的记录标记为 expired
- CROSSCHECK ARCHIVELOG ALL;
- -- 2) 看哪些归档已有备份(backup_count>0 才能安心删)
- SELECT sequence#, first_time, backup_count, deleted
- FROM v$archived_log WHERE deleted = 'NO' ORDER BY first_time;
- -- 3) 只删「已备份且完成时间在两天前」的归档,保留恢复窗口
- DELETE NOPROMPT ARCHIVELOG ALL BACKED UP 1 TIMES TO DEVICE TYPE DISK
- COMPLETED BEFORE 'SYSDATE-2';
复制代码
执行完再看 v$recovery_file_dest,SPACE_USED 应明显下降。如果发现大量归档 backup_count = 0,说明备份链断了——此时不要强删,先补一次归档备份再删。
步骤 3:根治——把删除策略固化进备份脚本
以后台定时任务每天跑一次「备份归档 + 顺手删除」,让 FRA 永远只保留一个滚动窗口:
- # crontab: 每天 01:30 归档备份,备份完即删已备份归档
- 30 1 * * * rman target / cmdfile=/home/oracle/scripts/arch_bak.rmn log=/home/oracle/logs/arch_bak_$(date +\%Y\%m\%d).log
复制代码- # arch_bak.rmn 内容
- BACKUP ARCHIVELOG ALL NOT BACKED UP 1 TIMES
- FORMAT '/backup/arch/arch_%d_%T_%s.bkp';
- DELETE NOPROMPT ARCHIVELOG ALL BACKED UP 1 TIMES TO DEVICE TYPE DISK
- COMPLETED BEFORE 'SYSDATE-2';
复制代码
有 Data Guard 环境的,删除策略要交给 RMAN 的保留策略来管,确保删的都已被备库应用:
- RMAN> CONFIGURE ARCHIVELOG DELETION POLICY TO APPLIED ON ALL STANDBY;
复制代码
步骤 4:告警前置
把 FRA 使用率做成监控项,80% 告警、90% 电话,别再等 ORA-00257 当报警器:
- -- 监控采集 SQL(接入 Zabbix/Prometheus 自定义 exporter 均可)
- SELECT round(space_used/space_limit*100, 1) AS fra_used_pct,
- round(space_reclaimable/space_limit*100, 1) AS fra_reclaim_pct
- FROM v$recovery_file_dest;
复制代码- # 简易 shell 门槛版,无监控系统时先顶上
- PCT=$(sqlplus -s / as sysdba @fra_pct.sql)
- [ "$PCT" -ge 80 ] && echo "FRA used ${PCT}% on $(hostname)" | mail -s "[WARN] FRA 80%" dba@example.com
复制代码
四、实操检查清单
- 每日检查 v$recovery_file_dest 使用率,80% 即告警、90% 电话升级
- 确认归档备份定时任务有执行日志且每天有新备份集生成(备份任务失败是最常见根因)
- 归档删除只走 RMAN(DELETE ARCHIVELOG),禁止任何人用 rm 直接删 FRA 里的文件
- 删除条件必须同时包含「已备份」与「保留窗口」(如 COMPLETED BEFORE SYSDATE-2)
- Data Guard 环境配置 ARCHIVELOG DELETION POLICY TO APPLIED ON ALL STANDBY 并在备库巡检 gap
- 每月演练一次「删光两天前归档后做时间点恢复」,验证保留窗口与恢复能力匹配
- FRA 配额变更记录在值班日志;db_recovery_file_dest_size 只允许止血临时调大,根因处理后回调
几个容易踩的坑
- 把配额当磁盘。df -h 有空间不代表没事,配额(db_recovery_file_dest_size)是独立记账,先查 v$recovery_file_dest 再下结论。
- rm 完以为删掉了。物理文件没了但账还在,空间不释放,还顺手制造了一堆 expired 记录。补救只能 CROSSCHECK ARCHIVELOG ALL + DELETE EXPIRED。
- 只备份不删除。备份脚本天天成功,归档也天天见涨,三个月后准时爆仓——备份和删除必须在同一脚本里闭环。
- 没确认备份就 DELETE ALL。DELETE ARCHIVELOG ALL 不带 BACKED UP 条件,等于亲手烧掉时间点恢复窗口,出事时只能全库恢复到最后一次全备。
- 止血后忘收口。配额临时扩到 80G 后没人回头处理根因,也没人回调配额,FRA 从此变成一个永远 99% 使用的黑洞。
治理前后对比
| 指标 | 治理前 | 治理后 | | FRA 使用率 | 100%(ORA-00257 事后发现) | 稳定 55%~65%,80% 告警 | | 数据库写操作挂起 | 本次 47 分钟 | 0(连续 90 天) | | 归档积压 | 518 个未备份归档 | 常态 ≤48 个(2 天窗口) | | 备份链连续性 | 断 3 天无人知 | 每日校验,断档即告警 | | 空间释放方式 | rm 后账实不符 | RMAN 统一删除,账实一致 | | 时间点恢复能力 | 已断档不可恢复 | 随时可恢复到 48 小时内任意时刻 |
归档日志治理的本质,是让「备份、删除、验证」三件事在同一套账本里闭环。配额只是水位线,闭环才是防波堤——把每天 01:30 的那条 cron 配好,ORA-00257 就再也不会在早上八点叫醒你。 |