多彩编程 多彩编程MZPH · CODE BLOG
ARTICLE DETAIL

文章详情

深耕前端与后端开发技术的一线实战笔记与踩坑复盘。

Oracle ORA-00257 归档日志撑爆恢复区:排查、应急清理与RMAN自动策略

Oracle ORA-00257 归档日志撑爆恢复区:排查、应急清理与RMAN自动策略 简介这份文档面向 Oracle 数据库运维与 DBA 人员聚焦归档日志写满引发的 ORA-00257 报错提供一套可落地的处理思路与操作记录。内容围绕 Archivelog 机制展开先说明该错误产生的原理再给出删除物理文件与登录 RMAN 释放归档空间两条主线并提示选择性删除日志、避免影响数据库可恢复性等注意事项适合遇到同类故障时对照排查。资源包共 1 个 doc 文件约 76KB以文字步骤与命令示例为主便于快速查阅与复制执行。目前已有 579 人学习下载说明该问题在实际运维中较为常见。读者可从中获得从查看归档占用比例、定位日志路径到 crosscheck 与 delete expired 释放空间的完整排错流程帮助恢复数据库正常运行。1. ORA-00257 不是磁盘满是归档日志把恢复区撑爆了凌晨两点监控告警炸了业务库连不上应用日志里清一色ORA-00257: archiver error. Connect internal only, until freed。很多人第一反应是「磁盘满了」冲上去df -h一看根分区还有 40% 空闲于是懵了。这个报错的真实含义是归档进程ARCH写不进去归档日志了数据库主动切断普通会话只留SYSOPER/SYSDBA能连。它卡的不是整个磁盘而是DB_RECOVERY_FILE_DEST指向的快速恢复区FRA或者你手工指定的归档目录。ORA-00257 是 Oracle DBA 绕不开的一道坎尤其在归档模式 RMAN 备份策略没配好的环境里几乎必然踩一次。它牵扯的东西很集中归档日志archivelog、快速恢复区、RMAN 的DELETE ARCHIVELOG策略、LOG_ARCHIVE_DEST配置。这篇不聊虚的就按我处理过的真实顺序走一遍——先搞清楚它为什么发生再给出能直接抄的排查命令和清理脚本最后讲怎么从根上让它别再犯。适合正在管 Oracle 单实例或 RAC、被归档空间反复折磨的运维和开发。热词里那些rman delete archive from until before 区别、oracle 监听服务无法启动本质都跟这套恢复区管理脱不了干系。2. 先定位ORA-00257 到底卡在哪一层2.1 归档写不进去的三个真实原因ORA-00257 的触发链条其实很短数据库处于 ARCHIVELOG 模式每次日志切换都要把在线重做日志完整复制成归档文件。归档目标写满或不可写ARCH 进程报错数据库进入「只允许特权连接」的保护状态。写不进去无非三种情况。第一种FRA 空间耗尽。这是最常见的。DB_RECOVERY_FILE_DEST_SIZE是个软限制Oracle 自己管这个配额归档、控制文件自动备份、闪回日志都往里塞。一旦用量顶到配额哪怕操作系统磁盘还有空间Oracle 也拒绝再写。第二种归档目录所在文件系统真的满了df -h一看 100%。第三种归档路径权限或挂载出了问题比如 NFS 掉线、目录被误删、属主被改ARCH 进程写文件直接失败。判断属于哪种先连上去看。注意报错期间普通账号连不上得用sqlplus / as sysdba走操作系统认证。# 以 sysdba 身份本地登录报错期间普通用户会被拒 sqlplus -S / as sysdba EOF set lines 200 pages 100 -- 看归档模式和当前归档目标 archive log list; -- 看 FRA 配额与已用量LIMIT_MB 是配额USED_MB 是实际占用 select name, space_limit/1024/1024 limit_mb, space_used/1024/1024 used_mb, space_reclaimable/1024/1024 reclaim_mb, number_of_files from v$recovery_file_dest; -- 按文件类型看 FRA 占用分布归档日志通常是大头 select file_type, percent_space_used, percent_space_reclaimable, number_of_files from v$recovery_area_usage; EOF这段脚本先回答两个问题归档开没开、FRA 用了多少。v$recovery_file_dest里的SPACE_USED逼近SPACE_LIMIT基本就实锤了。v$recovery_area_usage更细能看出是归档日志ARCHIVED LOG占满还是闪回日志FLASHBACK LOG在偷空间。我遇到过闪回区开着、db_flashback_retention_target设得很大结果闪回日志把 FRA 吃掉一半的情况光删归档治标不治本。2.2 用两条 SQL 确认归档日志堆积量定位到 FRA 之后得知道到底堆了多少归档、从什么时候开始堆的。这决定了你是删一批就够还是得改策略。-- 归档日志总量、最早和最晚的时间点 select count(*) total_cnt, round(sum(blocks*block_size)/1024/1024/1024, 2) total_gb, min(first_time) earliest, max(first_time) latest from v$archived_log where deleted NO; -- 按天统计归档生成量看每天涨多少判断清理频率 select trunc(first_time) day, count(*) cnt, round(sum(blocks*block_size)/1024/1024/1024, 2) gb from v$archived_log where deleted NO group by trunc(first_time) order by day desc;v$archived_log里DELETEDNO表示文件还在、没被标记删除。第一条给你总量和跨度第二条按天看增量。如果每天生成 20GB 归档、FRA 只有 100GB那你不配自动清理五天必炸。这个数字是后面定策略的核心依据别跳过。提示v$archived_log记录的是控制文件里的归档元数据如果控制文件被重建过历史记录可能不全以实际目录ls为准做交叉验证。3. 应急恢复让业务先连上来的四步操作3.1 最快的一招手工删归档 交叉校验业务断了第一优先级是恢复连接。最直接的办法是腾出 FRA 空间。但删归档有个铁律已经被 RMAN 备份过的归档才能删没备份就删等于把恢复能力扔了。所以顺序是先确认备份状态再删。# 1) 先看哪些归档已经备份过BACKUP 状态哪些没有 sqlplus -S / as sysdba EOF set lines 200 pages 100 select sequence#, first_time, deleted, status, backup_count from v$archived_log where deleted NO order by sequence#; EOFBACKUP_COUNT大于 0 表示这个归档至少被备份过一次删了相对安全。STATUS为AAvailable是正常可用D是已删除。确认之后用 RMAN 删最稳妥因为它会同步更新控制文件和 FRA 配额。# 2) 用 RMAN 删除已备份的归档释放 FRA rman target / EOF # 删除所有已备份过的归档日志并同步删除物理文件 DELETE ARCHIVELOG ALL BACKED UP 1 TIMES TO DEVICE TYPE DISK; # 如果只想删到某个时间点之前用这句注意 UNTIL TIME 是「之前」 # DELETE ARCHIVELOG UNTIL TIME SYSDATE-2; CROSSCHECK ARCHIVELOG ALL; DELETE EXPIRED ARCHIVELOG ALL; EOF这里必须把DELETE ARCHIVELOG ... UNTIL TIME和... BEFORE的区别讲清楚这是热词里问得最多的。UNTIL TIME SYSDATE-2删的是时间点之前生成的归档BEFORE系列如BEFORE SCN、BEFORE TIME语义上也是「早于」但在 RMAN 里UNTIL更常用于限定删除范围的上界BEFORE多用于DELETE ... BEFORE的保留策略表达。实操里我一般统一用UNTIL TIME语义清晰不易翻车。删完立刻CROSSCHECKDELETE EXPIRED把控制文件里指向已消失文件的记录清掉否则 FRA 配额不会真正释放。3.2 删完还是连不上检查这三处有时候归档删了业务还是报 00257别急着怀疑人生按顺序查。第一FRA 配额没刷新。v$recovery_file_dest的SPACE_USED如果没降说明控制文件里的记录没同步跑一次CROSSCHECK ARCHIVELOG ALL再DELETE EXPIRED。第二归档目标不止一个。LOG_ARCHIVE_DEST_N可能配了多个目的地你只清了主库本地备库或远端目的地还满着。查v$archive_dest的STATUS和ERROR列。第三ARCH进程卡死。极端情况下归档进程挂住需要ALTER SYSTEM ARCHIVE LOG CURRENT手动触发一次切换看能不能恢复。-- 查看所有归档目的地的状态和错误 select dest_id, status, destination, error from v$archive_dest where status ! INACTIVE; -- 手动触发日志切换验证归档是否恢复 alter system switch logfile; alter system archive log current;v$archive_dest的ERROR列会直接告诉你哪个目的地写失败、什么原因。这一步能排掉「删了本地但远端还满」的坑。ALTER SYSTEM ARCHIVE LOG CURRENT强制归档当前日志成功返回就说明 ARCH 进程活了。注意应急删除只是止血。如果每天归档增量大于 FRA 容量你今天删完过几天还会炸。真正的解法在下一章的自动清理策略。4. 根治把 RMAN 归档清理策略配成自动挡4.1 保留策略REDUNDANCY 还是 RECOVERY WINDOW应急之后必须配自动清理否则就是反复救火。RMAN 的保留策略有两种选错了要么空间浪费要么恢复时发现归档不够。REDUNDANCY n表示保留最近 n 份备份简单粗暴适合备份频率固定的场景。RECOVERY WINDOW OF n DAYS表示保证能恢复到 n 天内任意时间点更贴合「按时间回退」的需求但需要的归档量随业务写入量浮动。热词里rman 备份 按分钟回退说的就是后者——想精确回退到某个时刻归档必须连续完整。rman target / EOF # 方案A保留2份冗余备份 CONFIGURE RETENTION POLICY TO REDUNDANCY 2; # 方案B保证7天内任意时间点可恢复推荐给有回退需求的库 CONFIGURE RETENTION POLICY TO RECOVERY WINDOW OF 7 DAYS; # 开启控制文件自动备份并让归档删除策略自动生效 CONFIGURE CONTROLFILE AUTOBACKUP ON; CONFIGURE ARCHIVELOG DELETION POLICY TO BACKED UP 1 TIMES TO DISK; EOFCONFIGURE ARCHIVELOG DELETION POLICY TO BACKED UP 1 TIMES TO DISK是关键一句它告诉 Oracle归档只要被备份过一次就允许在 FRA 空间紧张时自动删除。配合RECOVERY WINDOWOracle 会在保证恢复窗口的前提下自动回收空间。这一步配好ORA-00257 基本就绝迹了。4.2 一个每天跑的清理脚本光配策略还不够我习惯加一个定时任务兜底每天凌晨跑一次删过期归档并输出日志。这样即使策略没触发也不会让 FRA 悄悄涨满。#!/bin/bash # /home/oracle/scripts/clean_arch.sh export ORACLE_SIDorcl export ORACLE_HOME/u01/app/oracle/product/19.0.0/dbhome_1 export PATH$ORACLE_HOME/bin:$PATH LOG/home/oracle/scripts/clean_arch_$(date %Y%m%d).log rman target / log$LOG EOF # 删除已备份且超出保留策略的归档 DELETE NOPROMPT ARCHIVELOG ALL BACKED UP 1 TIMES TO DISK; # 清理控制文件里失效的记录 CROSSCHECK ARCHIVELOG ALL; DELETE NOPROMPT EXPIRED ARCHIVELOG ALL; # 输出当前 FRA 使用情况方便事后核对 REPORT OBSOLETE; EOF # 把 FRA 用量追加到日志便于监控趋势 sqlplus -S / as sysdba $LOG EOF set lines 200 select name, round(space_used/1024/1024) used_mb, round(space_limit/1024/1024) limit_mb from v$recovery_file_dest; EOF脚本逻辑DELETE NOPROMPT免交互删除BACKED UP 1 TIMES保证只删有备份的CROSSCHECKDELETE EXPIRED清理元数据最后把 FRA 用量写进日志。挂到 crontab 每天 2 点跑# crontab -e 加入 0 2 * * * /home/oracle/scripts/clean_arch.sh参数上BACKED UP 1 TIMES里的数字可以调如果你备份更频繁、想更保守改成2 TIMES也行代价是空间回收慢一点。日志按天分文件出问题能回溯。4.3 FRA 配额和归档目录怎么设才合理DB_RECOVERY_FILE_DEST_SIZE设多大取决于你的归档日增量和保留窗口。经验公式配额 ≥ 日归档增量 × 保留天数 × 1.5。那个 1.5 是给控制文件备份、闪回日志留的余量。-- 查看当前配额 show parameter db_recovery_file_dest; -- 调整配额在线生效不用重启 alter system set db_recovery_file_dest_size 200G scope both;scopeboth同时改内存和 spfile重启不丢。如果 FRA 所在磁盘本身不大也可以把归档单独指到另一个大盘用LOG_ARCHIVE_DEST_1指定路径FRA 只放控制文件备份和闪回日志。这样职责分离归档满了不会连带把 FRA 拖垮。5. 避坑ORA-00257 处理中最容易翻车的五件事5.1 直接 rm 删归档文件控制文件不认账现象手工rm掉归档目录里的文件df -h空间回来了但v$recovery_file_dest的SPACE_USED纹丝不动过一会儿又报 00257。原因Oracle 的 FRA 配额是按控制文件里的记录算的不是按实际文件系统用量。你rm了文件控制文件里还记着这些归档存在配额自然不释放。解决永远用 RMAN 删或者删完立刻CROSSCHECK ARCHIVELOG ALLDELETE EXPIRED ARCHIVELOG ALL让控制文件同步。血泪经验手工rm是玄学操作能不用就不用。5.2 删了没备份的归档恢复时追悔莫及现象空间紧张图快把最近的归档全删了结果几天后要做时间点恢复发现归档链断了只能恢复到全备的时间点。原因DELETE ARCHIVELOG ALL不带BACKED UP条件时会把没备份的归档一起删掉。解决删除语句永远带BACKED UP n TIMES TO DEVICE TYPE DISK。删之前用LIST ARCHIVELOG ALL或查v$archived_log.BACKUP_COUNT确认备份状态。没备份的归档宁可先备份再删。5.3 只清主库忘了备库和远端目的地现象主库 FRA 清空了00257 还是反复出现。原因LOG_ARCHIVE_DEST_2指向备库或远端那边空间满了归档传输失败主库照样报错。解决查v$archive_dest的STATUS和ERROR确认所有VALID的目的地都健康。Data Guard 环境尤其要注意备库的 FRA。5.4 闪回日志偷偷吃掉 FRA现象归档删得干干净净FRA 用量还是居高不下。原因DB_FLASHBACK_RETENTION_TARGET设得大闪回日志在 FRA 里持续增长v$recovery_area_usage里FLASHBACK LOG占比很高。解决评估是否真需要闪回不需要就ALTER DATABASE FLASHBACK OFF需要就调小保留目标或把闪回区单独规划。别让闪回日志和归档抢同一块空间。5.5 归档目录权限被改ARCH 进程静默失败现象磁盘有空间、配额没满还是报 00257。原因归档目录属主或权限被误改或者 NFS 挂载掉了ARCH 进程写文件失败但不一定立刻报明显错误。解决检查归档目录的属主应为 oracle、权限一般 750 或 775NFS 场景确认挂载点在线。v$archive_dest.ERROR列通常会有线索。6. 进阶用归档生成速率反推 FRA 容量把 00257 挡在门外处理过几次 00257 之后我养成了一个习惯不等到报警而是定期算归档生成速率提前判断 FRA 够不够撑到下一个清理周期。这比事后救火省心得多。核心思路是拿v$archived_log的历史数据算日均增量再对比 FRA 配额和保留窗口看余量够几天。下面这段 SQL 直接给出「按当前速率FRA 还能撑几天」的估算。-- 估算 FRA 剩余可用天数 with rate as ( -- 近7天日均归档增量GB select round(sum(blocks*block_size)/1024/1024/1024 / greatest(trunc(sysdate) - trunc(sysdate-7), 1), 2) gb_per_day from v$archived_log where first_time sysdate - 7 and deleted NO ), fra as ( select round((space_limit - space_used)/1024/1024/1024, 2) free_gb from v$recovery_file_dest ) select r.gb_per_day, f.free_gb, round(f.free_gb / greatest(r.gb_per_day, 0.01), 1) days_left from rate r, fra f;GB_PER_DAY是近七天日均增量FREE_GB是 FRA 剩余空间DAYS_LEFT就是按当前速率还能撑几天。我一般把这个查询挂进日常巡检DAYS_LEFT低于保留窗口天数比如配了 7 天恢复窗口DAYS_LEFT掉到 5 以下就提前介入要么扩配额要么调清理策略。这样 00257 基本不会突然袭击。几个调优上的取舍值得说清楚。RECOVERY WINDOW设得越长需要的 FRA 越大但恢复灵活度越高设短了省空间代价是回退能力受限。我的习惯是核心业务库给 7 天窗口、FRA 按「日增量 × 10」配非核心库给 2 到 3 天就够。另外如果归档量实在大考虑把归档直接写到独立大盘、FRA 只留控制文件备份用LOG_ARCHIVE_DEST_1分离路径比一味扩 FRA 更经济。还有个容易忽略的点CONTROLFILE AUTOBACKUP也占 FRA 空间备份频繁的库这部分不小。定期REPORT OBSOLETE看看有没有该回收的别让它悄悄堆积。我自己踩过最深的一次坑是接手一个没人管的库FRA 配额设了 500G 但磁盘只有 200GSPACE_LIMIT是个虚数实际磁盘先满了报错信息还指向 FRA查了半天才发现是配额和物理磁盘对不上。从那以后我立了个规矩配 FRA 之前先df -h确认物理磁盘配额永远留 20% 余量绝不把DB_RECOVERY_FILE_DEST_SIZE设得比实际可用空间还大。归档管理这事防大于治把速率算清楚、策略配到位比半夜爬起来救火强太多。希望帮到你。本文还有配套的精品资源点击获取
返回列表