简介:面向 Oracle 数据库运维人员与 DBA 的 ORA-00257 归档日志满故障处理文档,聚焦 Archivelog 空间占满导致数据抽取任务中断这一典型场景,适合具备基础 SQL*Plus 与 RMAN 操作能力、需要快速恢复数据库可用性的技术人员参考。压缩包共 1 个 doc 文件,约 76KB,以图文结合方式记录完整排错过程。文档围绕「删除物理文件 + 登录 RMAN 释放逻辑空间」两条主线展开,包含通过 v$flash_recovery_area_usage 查看占用比例、用 show parameter recover 定位日志路径与空间大小、选择性清理归档文件,以及 crosscheck archivelog all 与 delete expired archivelog all 的配合使用,并附有关键命令截图与空间释放后的验证结果。已有 581 人学习,可作为归档日志告警时的速查手册与操作参照。
1. 凌晨两点告警:ORA-00257 不是“删日志”这么简单
凌晨两点,数据抽取任务突然停了,监控面板上一条 ORA-00257 红得刺眼。很多人第一反应是“归档满了,删日志”,可真到服务器上一看,/backup/flash_recovery_area目录里躺着两天的归档,v$flash_recovery_area_usage显示占用 89.78%,再涨一点数据库就写不进去了。这份《ORA-00257错误.doc》记录的就是一次完整的处置过程:先删物理归档文件,再进 RMAN 做 crosscheck 和 delete expired,把逻辑空间释放掉。它适合两类人——一是半夜被这个错误叫起来、需要照着步骤把库救回来的 DBA;二是想搞清楚“物理删除”和“RMAN 逻辑释放”到底差在哪、为什么删了文件空间却没回来的运维。下面按我拆文档的顺序,把每一步的命令、参数和翻车点讲透。
2. 先看懂归档空间:v$flash_recovery_area_usage 与 show parameter recover
2.1 为什么归档会满,满了为什么业务会停
Oracle 的 archivelog 机制是为了保证数据库可恢复:每次日志切换,联机重做日志会被归档到闪回恢复区(FRA),记录数据库的所有变化。FRA 有配额上限,文档里这个库的db_recovery_file_dest_size是 160G,路径是/backup/flash_recovery_area。当归档把配额吃满,数据库无法再归档,联机日志不能切换,写操作就会被挂起——表现出来就是数据抽取任务停止、应用报 ORA-00257。这里有个反直觉的点:错误码说的是“归档日志满”,但真正卡住的是“无法归档导致日志切换失败”,所以光看磁盘df -h还有空间没用,要看的是 FRA 配额占用比例。文档里 89.78% 这个数字就是从v$flash_recovery_area_usage查出来的,它是判断“要不要动手”的第一手依据,比看目录大小靠谱得多。
2.2 两条查询命令:占用比例和路径配额
处置前先把现场摸清楚,文档给的两条 SQL 就是干这个的。第一条看各类文件在 FRA 里的占用百分比,第二条看 FRA 的路径和配额大小。我一般会再加一条看归档切换频率,判断是“突发暴涨”还是“长期没清理”。
-- 以 sysdba 身份登录后执行 sqlplus /nolog conn /as sysdba -- 1. 查看 FRA 各类文件占用比例,ARCHIVELOG 那一行就是归档占比 select * from v$flash_recovery_area_usage; -- 2. 查看 FRA 路径与配额大小 show parameter recover; -- 3. 补充:看最近归档生成速率,判断是暴涨还是长期堆积 select trunc(completion_time) as day, count(*) as cnt, round(sum(blocks*block_size)/1024/1024/1024, 2) as gb from v$archived_log where completion_time > sysdate - 7 group by trunc(completion_time) order by day;逻辑说明:v$flash_recovery_area_usage的PERCENT_SPACE_USED列直接给出占用比例,文档里 89.78 就是这一列的值;show parameter recover输出里db_recovery_file_dest是路径、db_recovery_file_dest_size是配额。第三条是我补的,按天统计归档量和大小,如果某天突然翻倍,说明有大批量操作或备份策略出了问题,光删日志治标不治本。参数上要注意:db_recovery_file_dest_size单位默认是字节,show parameter会显示成 160G 这种可读格式,改配额用alter system set db_recovery_file_dest_size=200G;,但扩容只是缓兵之计,清理策略才是根本。
2.3 判断该删哪些:保留策略与“不要全删”的边界
文档里特别强调“可选择性删除里面的日志,不要全部删除”,但它这次操作删了全部,原因是“这是新的数据库服务器,没有其他的操作记录”。这句话是整个文档最容易被误读的地方。归档日志是可恢复性的底线,删掉就意味着对应时间段的恢复能力归零。判断能不能删,看的是恢复策略:如果库有每日全备加归档备份,且备份已成功、已异地保存,那么备份点之前的归档可以清;如果库没有有效备份,删归档等于把库变成“只能前滚不能回退”的状态。我一般会先查备份记录再动手:
-- 查看最近归档备份情况,确认备份成功后再决定删除范围 list backup of archivelog all summary; -- 在 RMAN 中执行 -- 或在 SQL*Plus 中查备份作业历史(视部署的备份工具而定) select * from v$rman_backup_job_details where start_time > sysdate - 3 order by start_time desc;只有确认“这些归档已经有备份、且备份可用”,才轮到物理删除。文档场景是全新库、无业务记录,所以全删风险可控;换成生产库照抄“rm -rf 整个 archivelog 目录”,就是血泪教训的开始。
3. 物理删除与 RMAN 逻辑释放:两步走完整操作
3.1 物理删除:rm 之前先确认路径和文件
文档的操作顺序是:切到 oracle 用户,进 SQL*Plus 确认路径,然后到服务器上删物理文件。这里的关键是“路径必须和show parameter recover的输出完全一致”,不能凭记忆。文档里路径是/backup/flash_recovery_area,归档在它下面的archivelog/日期目录里,比如2012_06_10、2012_06_11两个目录。
# 1. 切换到 oracle 用户(文档用 su - oracle) su - oracle # 2. 先确认 FRA 路径,和数据库参数对齐 # 在 SQL*Plus 中执行 show parameter recover 得到路径后,再回 shell 操作 # 3. 进入归档目录,先看再删,确认日期目录和文件数量 cd /backup/flash_recovery_area ls -lh archivelog/ du -sh archivelog/* # 4. 按日期目录删除(文档删的是 2012_06_10、2012_06_11 两个目录) # 生产环境建议先备份或确认已有归档备份,再执行 rm -rf /backup/flash_recovery_area/archivelog/2012_06_10 rm -rf /backup/flash_recovery_area/archivelog/2012_06_11 # 5. 删完确认目录已空、空间已释放 ls -lh archivelog/ df -h /backup逻辑说明:ls -lh和du -sh是删之前的“后悔药”,先看清删的是什么、占多少;rm -rf按日期目录删而不是删整个archivelog,是为了保留其他日期的归档。参数上,-r递归、-f强制不提示,这两个参数组合在生产环境要慎用,我习惯先ls再删,或者用find按时间精确匹配。注意:物理删除只是把文件从磁盘拿掉,Oracle 的控制文件里这些归档仍然登记为“存在”,FRA 配额占用不会立刻下降——这就是下一步 RMAN 要解决的问题。
3.2 RMAN crosscheck:把已删文件标记为 expired
物理文件没了,控制文件还认为它在,直接delete archivelog会报找不到文件。正确做法是先crosscheck,让 RMAN 去核对磁盘上的实际文件,把对不上的标记成 expired(过期),再删这些 expired 记录。
# 1. 登录 RMAN(文档用 rman target /,本地 OS 认证) rman target / # 2. 核对所有归档,磁盘上不存在的会被标记为 expired RMAN> crosscheck archivelog all; # 3. 删除已标记为 expired 的归档记录,释放 FRA 逻辑空间 RMAN> delete expired archivelog all; # 提示确认时输入 YES逻辑说明:crosscheck archivelog all是“对账”,它遍历控制文件里登记的归档,逐个去磁盘找文件,找不到就标 expired;delete expired archivelog all只删 expired 记录,不动磁盘上真实存在的文件,所以安全。参数上,all表示全部归档,也可以限定时间范围如archivelog from date '2012-06-10'。文档里提示“输入 YES 即可”,是因为 RMAN 删除前会列出待删列表让你确认,这一步别手快,扫一眼列表确认删的是 expired 而不是 available。执行完再回 SQL*Plus 查v$flash_recovery_area_usage,占用比例应该明显下降,文档最后那张图就是这个验证动作。
3.3 验证释放结果与恢复归档能力
删完不能只看比例降了就收工,还要确认数据库能正常归档、业务能恢复写入。我一般按下面几步验证:
-- 1. 确认 FRA 占用比例已下降 select * from v$flash_recovery_area_usage; -- 2. 手动切换日志,确认能正常归档(会生成新归档) alter system switch logfile; -- 3. 查看最新归档是否成功生成 select sequence#, name, completion_time, status from v$archived_log where completion_time > sysdate - 1/24 order by sequence# desc; -- 4. 确认数据库可写、无归档挂起 select * from v$archive_processes; -- 或查 v$log 状态逻辑说明:alter system switch logfile强制一次日志切换,如果归档空间已释放、归档进程正常,新归档会成功写入 FRA;如果还报 ORA-00257,说明释放没生效或配额仍不够。v$archived_log的status列应为A(可用)。这一步是文档没写但必须做的“闭环验证”,否则你以为修好了,下一次日志切换又挂。
4. 避坑清单:五条踩过的坑与排查路径
4.1 坑一:只删物理文件,空间比例不降
现象:rm删完目录,df -h空间回来了,但v$flash_recovery_area_usage占用还是 89%。原因:Oracle 的 FRA 配额统计基于控制文件登记,物理文件没了但记录还在,RMAN 不 crosscheck 就不会更新。解决:按第 3.2 节走crosscheck archivelog all加delete expired archivelog all,两步缺一不可。排查时先查v$archived_log里这些归档的deleted状态,确认记录是否还在。
4.2 坑二:直接 delete archivelog all 报文件不存在
现象:跳过 crosscheck 直接delete archivelog all,RMAN 报ORA-19809或找不到文件。原因:控制文件认为文件存在,RMAN 去删时磁盘上没有,操作失败。解决:先crosscheck标 expired,再delete expired。如果已经误操作,重新 crosscheck 一遍即可,不会损坏数据。
4.3 坑三:全删归档导致无法恢复
现象:照文档删了整个 archivelog 目录,后来需要恢复到某个时间点,发现归档缺失。原因:文档场景是全新库无业务记录,生产库全删等于放弃该时间段恢复能力。解决:删之前确认归档已有备份且备份可用,按备份点之前的范围删,保留最近一段。排查用list backup of archivelog all确认备份覆盖范围,没有备份就别删。
4.4 坑四:路径看错,删了非 FRA 目录
现象:show parameter recover显示路径是/backup/flash_recovery_area,但有人凭经验去删$ORACLE_BASE/flash_recovery_area。原因:FRA 路径可被参数改到任意位置,不能想当然。解决:每次操作前用show parameter db_recovery_file_dest确认实际路径,cd进去pwd核对后再删。这个坑翻车代价最大,删错目录可能连带备份一起没了。
4.5 坑五:释放后不验证,下次切换又挂
现象:比例降了,以为完事,结果几小时后 ORA-00257 再次出现。原因:归档生成速率大于清理速率,或者配额本身太小。解决:释放后做alter system switch logfile验证归档正常,并评估配额是否要调大、是否要加定时清理任务(如每天 crosscheck 加 delete expired 的脚本)。排查看v$archived_log按天统计的生成量,和配额对比算能撑几天。
5. 把一次性救火变成例行巡检:归档清理脚本与配额监控
文档记录的是“出事—处置”的一次性动作,但 ORA-00257 这种错误,靠半夜救火成本太高。我的习惯是把第 3 章的步骤固化成例行巡检:每天查一次 FRA 占用比例,超过阈值就触发 crosscheck 加 delete expired,同时监控归档生成速率,提前判断配额够不够。下面这个脚本是我常用的骨架,跑在 oracle 用户下,配合 crontab 每天执行,输出写日志。
#!/bin/bash # 归档空间巡检脚本,oracle 用户执行 export ORACLE_SID=your_sid LOG=/home/oracle/arch_clean_$(date +%Y%m%d).log # 1. 查 FRA 占用比例,超过 80 触发清理 USED=$(sqlplus -s / as sysdba <<EOF set heading off feedback off select percent_space_used from v$flash_recovery_area_usage where file_type='ARCHIVELOG'; exit EOF ) echo "$(date) ARCHIVELOG used: ${USED}%" >> $LOG # 2. 超过阈值则 crosscheck + delete expired if [ $(echo "$USED > 80" | bc) -eq 1 ]; then rman target / log=$LOG append <<EOF crosscheck archivelog all; delete noprompt expired archivelog all; exit EOF echo "$(date) cleanup done" >> $LOG fi逻辑说明:percent_space_used取的是归档占比,阈值 80 是经验值,留 20% 缓冲给突发归档;delete noprompt免交互,适合脚本,但前提是只删 expired,不会误删有效归档。参数上ORACLE_SID要换成实际实例名,bc用于浮点比较,没装的话可以用 awk 替代。这个脚本只解决“已删文件的对账”,不解决“该不该删有效归档”,后者仍要结合备份策略人工判断。
再补一个配额监控的查询,用来判断“清理速度跟不跟得上生成速度”:
| 监控项 | 查询/命令 | 判断标准 |
|---|---|---|
| FRA 占用比例 | v$flash_recovery_area_usage的PERCENT_SPACE_USED | 持续高于 80% 需清理或扩容 |
| 每日归档生成量 | v$archived_log按天count和sum(blocks*block_size) | 对比配额算可撑天数 |
| 归档备份覆盖 | RMANlist backup of archivelog all summary | 备份点之前的归档才可删 |
| 归档进程状态 | v$archive_processes或v$log状态 | 有挂起说明归档受阻 |
最后说个我自己的习惯:每次处理完 ORA-00257,我都会把当时的v$flash_recovery_area_usage输出、删除的日期目录、crosscheck 结果存一份到变更记录里。不是为了交差,是因为下一次再出同样错误,这份记录能让我三分钟判断“是配额问题还是生成暴涨”,而不是从头再摸一遍。归档清理这事,删文件只是动作,搞清“为什么满、删了能不能恢复”才是根本。希望帮到你。
本文还有配套的精品资源,点击获取