归档日志是 Oracle 的"时光机",没有它,恢复就无从谈起。但归档日志也是生产环境的"空间杀手"。我见过太多库因为归档目录满了直接 HANG 住,业务全停。最惨的一个客户,FRA(Fast Recovery Area)设了 500GB,结果周末大促 redo 暴增,FRA 撑满,数据库挂了一小时,损失了几十万订单。这篇文章把归档模式原理、FRA 机制、归档删除策略、以及空间监控的实战方法拆清楚。
1 归档模式不是开了就完事,是持续的空间消耗
非归档模式下,redo 日志切换后直接被覆盖,不保留历史。归档模式下,每次日志切换,ARCn 进程把刚写满的在线日志拷贝到归档目录。如果数据库每秒产生 10MB redo,日志组 1GB,那么每 100 秒切换一次,每天产生约 860 个归档文件,占用 860GB。这还没算 RAC 多节点的情况。所以开归档之前,必须先算好空间需求:日均 redo 量 × 保留天数 × 1.5(余量)。
FRA 是 Oracle 管理的统一恢复区,放归档日志、备份集、闪回日志、控制文件自动备份。FRA 的好处是 Oracle 自动管理空间:文件过时(obsolete)后自动删除。坏处是如果空间满了,而且里面的文件都没过时,数据库会暂停归档,进而暂停 redo 写入,最后实例 HANG 住。这是 Oracle 的保护机制——宁可停库,也不丢归档。
2 归档删除策略:RMAN 保留策略 vs 备库应用状态
归档什么时候能删?有两个判断标准:一是 RMAN 保留策略(CONFIGURE RETENTION POLICY),比如 REDUNDANCY 2(保留两份全备)或 RECOVERY WINDOW 7 DAYS(保留 7 天恢复窗口)。二是备库应用状态,如果配置了 DataGuard,归档必须等备库应用后才能删(CONFIGURE ARCHIVELOG DELETION POLICY TO APPLIED ON ALL STANDBY)。
最危险的配置是:开了 DataGuard,但 RMAN 没配 deletion policy,默认是 NONE,RMAN 认为归档"没过时",FRA 里的归档越积越多。等 FRA 满了,数据库 HANG。我们给一个客户排查时,发现 FRA 500GB 全满,归档从三个月前就开始堆积。根因是备库停了两个月,没人管,主库以为备库还需要这些归档,不敢删。解决办法:先临时把 deletion policy 改成 NONE,手动删除过期归档,然后恢复备库,再把 policy 改回 APPLIED ON ALL STANDBY。
3 实验:模拟 FRA 满导致的数据库 HANG
实验环境:Oracle 19c,FRA 设 5GB(故意设小),归档模式开启。
-- 查看 FRA 设置
SHOW PARAMETER DB_RECOVERY_FILE_DEST;
SHOW PARAMETER DB_RECOVERY_FILE_DEST_SIZE;
-- 设置 FRA 为 5GB
ALTER SYSTEM SET DB_RECOVERY_FILE_DEST_SIZE = 5G SCOPE = BOTH;
ALTER SYSTEM SET DB_RECOVERY_FILE_DEST = '/u01/fra' SCOPE = BOTH;
-- 制造大量 redo,快速填满 FRA
-- 方法:大量 INSERT + 频繁日志切换
BEGIN
FOR i IN 1..100 LOOP
EXECUTE IMMEDIATE 'ALTER SYSTEM SWITCH LOGFILE';
INSERT INTO big_table SELECT * FROM big_table; -- 快速膨胀
COMMIT;
END LOOP;
END;
/
-- 监控 FRA 使用率
SELECT
ROUND(SPACE_USED/1024/1024/1024,2) USED_GB,
ROUND(SPACE_LIMIT/1024/1024/1024,2) LIMIT_GB,
ROUND((SPACE_USED/SPACE_LIMIT)*100,2) PCT_USED
FROM V$RECOVERY_FILE_DEST;
-- 监控归档状态
SELECT dest_name, status, error FROM v$archive_dest WHERE dest_id = 1;
-- 当 FRA 满时,alert log 会出现:
-- ORA-19809: limit exceeded for recovery files
-- ORA-19804: cannot reclaim 52428800 bytes disk space from 5368709120 limit
-- 然后数据库挂起,等待 ARCn 完成归档
实验结果:FRA 使用率达到 100% 后,新的日志切换无法产生归档,ARCn 进程报错 ORA-19809。此时如果继续产生 redo,LGWR 会被阻塞,等待 ARCn 释放空间。会话的 DML 操作挂起,等待事件变成 log file switch (archiving needed)。整个数据库进入"假死"状态,只有查询能执行(如果 undo 够用)。
应急处理:
-- 1. 紧急扩容 FRA
ALTER SYSTEM SET DB_RECOVERY_FILE_DEST_SIZE = 10G SCOPE = BOTH;
-- 2. 或者手动删除已备份且已应用到备库的归档
RMAN> DELETE ARCHIVELOG ALL COMPLETED BEFORE 'SYSDATE-1';
-- 3. 如果备库长期不用,临时允许删除未应用归档(谨慎!)
RMAN> CONFIGURE ARCHIVELOG DELETION POLICY TO NONE;
4 那个周末大促的惨案
客户是一个电商平台,FRA 500GB,平时够用。但双十一大促期间,redo 产生速率从平时的 50MB/s 涨到 800MB/s,一天产生 70TB redo(压缩后归档约 7TB)。FRA 500GB 在半小时内就被撑满,数据库 HANG。DBA 当时不在现场,运维按"惯例"删了 FRA 里的归档文件(用 rm 命令直接删操作系统文件)。结果 Oracle 不知道文件被删了,V$RECOVERY_FILE_DEST 里空间占用还是显示 100%,因为 Oracle 靠控制文件记录 FRA 内容,不是实时扫描磁盘。最后必须用 RMAN 的 CROSSCHECK ARCHIVELOG ALL 同步状态,然后 DELETE EXPIRED ARCHIVELOG ALL 清理控制文件记录,数据库才恢复。这个教训告诉我们:归档必须用 RMAN 删,不能 rm。
【踩坑笔记】归档管理的 SOP:第一,FRA 大小至少预留 3 天峰值归档量,且必须监控,使用率超过 80% 告警。第二,必须用 RMAN 删除归档,严禁操作系统 rm。第三,开了 DataGuard 的库,要同时监控备库的 apply lag,lag 超过 24 小时立即告警,防止主库归档堆积。第四,定期做 RMAN 备份后,用 DELETE OBSOLETE 清理过期备份集,释放 FRA 空间。
5 总结:归档是保险,也是负债
归档日志是恢复的必需品,但也是磁盘空间的持续消耗者。管理不好,保险变负债。三条铁律:第一,开归档前算好空间,FRA 大小按"峰值 redo 量 × 3 天 × 2"设。第二,RMAN 保留策略和归档删除策略要配套,别让它"只进不出"。第三,监控 FRA 使用率,80% 告警,90% 立即处理。最后送一句话:归档日志是数据库的"黑匣子",黑匣子满了,飞机就得迫降。别让迫降变成坠毁。