简介:ORA-00257错误是Oracle数据库在归档日志占满闪回恢复区时抛出的典型故障,会导致数据抽取任务停止甚至数据库异常。这份doc文档完整记录了从问题定位到空间释放的实战处理流程,面向DBA及运维人员,适合处理生产环境归档空间告警时查阅。内容以实际环境为例,先通过v$flash_recovery_area_usage查看占用比例(如89.78%),再用show parameter recover确认日志路径与空间限额,接着安全删除物理归档日志,最后登录RMAN执行crosscheck archivelog all和delete expired archivelog all完成逻辑空间回收;同时强调应选择性删除日志、避免影响数据库可恢复性。资源为单个doc文档,大小76KB,仅1个文件,步骤紧凑且包含关键命令,参考价值高。已有579人浏览学习,可帮助运维人员快速解决ORA-00257错误并预防同类问题。
1. ORA-00257:一个突然让生产库“假死”的归档错误
某天中午,某公司客服系统突然全部卡住,应用侧报的是“ORA-00257: archiver error”。数据库管理员第一反应通常是查表空间使用率,结果发现表空间明明健康得很。真正的原因是:数据库处于归档模式,日志切换后新的重做日志无法写入归档目标,归档进程一直失败,导致所有提交事务被阻塞。这个错误看似是“空间问题”,影响却是全局性的,比表空间满更隐蔽、更急于处理。这篇文章会讲清楚ORA-00257的触发机制、诊断动作、恢复步骤和日常预防,适合正在管理生产库或刚遇到这个报错的人。
2. ORA-00257 的触发机制:归档进程一停,整个库跟着遭殃
2.1 从“日志写不完”到“全局事务阻塞”的因果链
数据库在运行期间,事务产生的重做记录先写入在线重做日志组。在线日志组通常是两到三组轮流使用,当一组写满,数据库执行日志切换(log switch),让另一组接替写入。切换之前,有一个前提条件:如果数据库启用了归档模式,ARCH进程必须先把这一组日志完整归档到归档目标,只有归档成功,这组日志才能被复用以继续写入。
如果归档目标没有可用空间,ARCH进程会持续报错。日志切换本来可以正常发生,但归档失败后,对应的日志组仍然处于“待归档”状态,数据库不会复用它。随着业务继续写入,剩下的日志组也会一个接一个被写满。当所有日志组都处于“待归档”或“正在使用”状态时,数据库便无法再分配新的日志组给任何事务。
这时候,所有涉及DML操作的会话都会排队等待。SELECT查询通常还能勉强执行,但是任何INSERT、UPDATE、DELETE都可能被卡住。更让人头疼的是,应用连接池里的空闲连接会被慢慢占满,新请求开始报连接超时。很多运维人员看到这一堆应用错误,第一反应是排查网络或监听,折腾半天才发现方向错了。
Alert日志里的报错信息其实比想象中直白。每次ARCH失败,告警日志都会追加一条ORA-00257记录。如果是11g及以上版本,常见的完整报错格式类似:
ORA-00257: archiver error. Connect to internal>, 28000, 0这个报错的文本是固定的,但真正的原因可能会在它前后出现。比如ORA-19809是“空间限制超出”,ORA-16038是“日志无法归档”。连带的错误越多,越说明问题积累已经有一段时间了。第一次看到这个报错时,不要只盯着表面,也别急着重启数据库,先看告警日志的时间线。
2.2 闪回恢复区与归档目标:别把两个空间混为一谈
归档日志写到哪,这是理解ORA-00257的关键。数据库有两个容易混淆的地方:一个是显式指定的归档目标,另一个是闪回恢复区(Flash Recovery Area,简称FRA)。
显式归档目标由参数LOG_ARCHIVE_DEST_n控制。比如:
ALTER SYSTEM SET LOG_ARCHIVE_DEST_1='LOCATION=/u01/archivelog';这种情况下,归档日志直接写到/u01/archivelog这个文件系统目录,空间是否够用取决于这个目录所在的磁盘。
而FRA是数据库自己管理的一块统一存储区域,由两个参数控制:DB_RECOVERY_FILE_DEST指定位置,DB_RECOVERY_FILE_DEST_SIZE指定大小上限。如果没有配置LOG_ARCHIVE_DEST_n,数据库默认会把归档日志写到FRA。也就是说,ORA-00257的排查路径要从这两组参数开始。
参数写法上有一个容易踩坑的点:DB_RECOVERY_FILE_DEST_SIZE的单位是字节,不是GB。如果写成20G会被直接报错,正确写法是:
ALTER SYSTEM SET DB_RECOVERY_FILE_DEST_SIZE=20G SCOPE=BOTH;这条命令本身没问题,因为Oracle允许使用后缀简化单位。但要注意的是,修改参数只是修改了“上限”,不是立刻给FRA腾出了空间。如果磁盘实际可用空间只有5G,你把它设成20G,数据库也会继续尝试往里面写,直到真的写不进去。
FRA里的内容不只有归档日志,还包括闪回日志、控制文件自动备份、RMAN备份集等。所以你在排查时需要清楚:空间是被谁占掉的,不能只盯着归档日志看。这也是为什么很多人在手动删了归档日志之后,FRA的占用率还是没有变化,后面第5章我会专门说这个坑。
2.3 为什么“空间问题”最容易翻车:三个复发场景
很多系统跑了好几年都没出过这个错,突然某天爆发,往往不是偶然。我整理过几个高发场景,基本覆盖了大多数生产库遇到ORA-00257的实际情况。
第一个场景:数据库从非归档模式切换成归档模式,但FRA大小沿用默认值。这种配置下,一旦日志量稍有波动,FRA很快就撑满了。第二个场景:业务侧做大批量数据更新,比如报表重算、全表UPDATE、批量INSERT,每小时生成的归档日志数量是日常的十几倍。第三个场景:备份策略只做了备份而不清理过期归档,RMAN备份越来越多,占用的FRA空间越来越大,最终把归档日志的写入空间挤没了。
可以用一张表来快速判断方向:
| 典型现象 | 大概率原因 | 排查入口 |
|---|---|---|
| 告警日志只报ORA-00257 | FRA空间不足 | 查V$FLASH_RECOVERY_AREA_USAGE |
| 归档目标路径磁盘满 | 文件系统空间不足 | 用df -h检查 |
| 报错里带ORA-19809 | FRA空间配置不合理 | 检查DB_RECOVERY_FILE_DEST_SIZE |
| 报错里带ORA-16038 | 归档日志写入失败 | 检查归档目标状态和权限 |
以后遇到类似报错,先对号入座,能省不少力气。
3. 诊断确认:三步看清是哪个环节堵住了
3.1 第一步:去alert日志里找ORA-00257的上下文
不要在还没确认原因的时候就把数据库重启一遍,那是最不划算的做法。正确顺序是先看告警日志。在11g之后,日志默认路径在ADR目录下,一般格式是:
$ORACLE_BASE/diag/rdbms/<db_unique_name>/<instance_name>/trace/alert_<instance_name>.logdb_unique_name和instance_name不一定相同,直接在服务器上确认更稳妥:
adrci exec="show home" adrci exec="show alert -tail 200"用adrci的好处是它自动定位到当前实例的日志目录,不用手动拼路径。如果想用传统方式直接看,可以先查diagnostic_dest参数来定位日志目录:
show parameter diagnostic_dest;拿到路径后,用grep把ORA-00257前后的几行带出来:
grep -B 5 -A 5 "ORA-00257" alert_<instance_name>.log | tail -n 60从上下文里能读出三个信息:错误第一次出现的时间、出现频率、是否伴随其他ORA错误。如果报警已经存在了好几个小时但没有其他严重错误,说明数据库大概率还没完全hang住,处理时间相对宽裕。但如果是刚刚开始报,就要马上动手,不能拖。
3.2 第二步:用视图确认FRA占用情况
登录数据库后,第一优先查FRA的使用率。这个视图直接反映FRA里每类文件占了多少空间:
SELECT FILE_TYPE, PERCENT_SPACE_USED, PERCENT_SPACE_RECLAIMABLE, NUMBER_OF_FILES FROM V$FLASH_RECOVERY_AREA_USAGE;输出里你会看到类似ARCHIVED LOG 72.5 0 180这样的行。重点看PERCENT_SPACE_USED,尤其是ARCHIVED LOG和FLASHBACK LOG两行。如果两者相加已经接近100%,基本可以确认FRA满就是罪魁祸首。
再看一下FRA的大小上限和当前实际位置:
SHOW PARAMETER DB_RECOVERY_FILE_DEST; NAME TYPE VALUE ------------------------------------ ----------- ------------------------------ db_recovery_file_dest string /u01/fra db_recovery_file_dest_size big integer 10GSHOW PARAMETER返回的是单实例视图,内容比较直观。如果DB_RECOVERY_FILE_DEST_SIZE的值是0,说明FRA没启用,这时候归档目标极可能是显式的LOG_ARCHIVE_DEST_n,你需要继续查:
SHOW PARAMETER LOG_ARCHIVE_DEST;3.3 第三步:判断是FRA满还是磁盘本身满
确认了FRA容量和占用,还要确认物理磁盘的状态。因为有一种情况是FRA上限设得很大,但磁盘实际空间不够,这时候数据库也会报ORA-00257,原因却是“写不进真实空间”。
在服务器上执行:
df -h /u01/fra看Avail列是否为零或很小。如果FRA目标路径所在磁盘几乎没有剩余空间,那么就算FRA使用率只有30%,归档一样会失败。
还有一种情况容易被忽略:归档目标设置了多个位置。LOG_ARCHIVE_DEST_n可以配多个,比如同时写入本机路径和远程备库路径。主库本机路径没问题,但备库路径如果写入失败,ARCH进程仍然会报错,甚至导致主库被拖住。排查时要把所有归档目标都过一遍:
SELECT DEST_NAME, DESTINATION, STATUS, ERROR FROM V$ARCHIVE_DEST WHERE DEST_ID <= 10 AND DESTINATION IS NOT NULL;如果ERROR列里有非空内容,直接按这个错误去分析,比只盯着ORA-00257更高效。
4. 应急恢复:先让数据库恢复写入,再谈预防
4.1 标准抢救流程:用RMAN删除过期归档日志
确认是FRA空间不足之后,最快的恢复方式就是清理归档日志。清理动作必须通过RMAN来做,而不是直接在操作系统里rm文件。RMAN删除命令会同步更新控制文件里的元数据,避免留下“已存在的归档文件但却找不到对应文件记录”的隐患。
常用的清理命令是:
rman target / <<EOF DELETE NOPROMPT ARCHIVELOG ALL COMPLETED BEFORE 'SYSDATE-1'; EOF这个命令会删除创建时间在一天之前的所有归档日志,NOPROMPT表示不需要逐条确认。SYSDATE-1是Oracle的日期表达式,表示当前时间往前推一天。如果你不确定这个删除会不会影响尚未备份的归档,可以先用REPORT OBSOLETE或LIST BACKUP确认现有备份保留情况。
确认之后再执行删除:
rman target / <<EOF CROSSCHECK ARCHIVELOG ALL; DELETE NOPROMPT EXPIRED ARCHIVELOG ALL; EOFCROSSCHECK会把控制文件里记录的归档日志和实际磁盘文件做比对,标记出不存在的文件。DELETE EXPIRED清理这些失效记录。这一步能避免控制文件里的记录与实际文件不一致,是很多DBA容易跳过的动作。
如果保留了GDS或Data Guard环境,RMAN删除时可能会触发备库的gap检测,所以在清理完成后要检查备库的日志应用状态。方法是查主库和备库的V$ARCHIVE_GAP:
SELECT * FROM V$ARCHIVE_GAP;没有返回结果,说明没有归档断层,可以安心。
4.2 调大DB_RECOVERY_FILE_DEST_SIZE不是万能的
清理完归档日志,数据库通常已经恢复写入。为了防止短时间内再次爆发,很多人会顺手把FRA调大。这个方向没错,但要注意限制条件。
ALTER SYSTEM SET DB_RECOVERY_FILE_DEST_SIZE=20G SCOPE=BOTH;SCOPE=BOTH表示同时写入当前实例和参数文件,之后重启也生效。这句话本身不难,难在前提:物理磁盘剩余空间是否够20G。如果磁盘总共只有15G可用,你把FRA调到20G,数据库执行归档时照样报写入失败,只是报错信息从ORA-00257变成ORA-19809。
正确做法是先确认磁盘容量:
df -h /u01/fra确认充足的剩余空间后,再调参数。调大多少合适,主要看归档日志生成速率。你可以用归档日志的大小变化来估算:
SELECT TRUNC(COMPLETION_TIME) DAY, ROUND(SUM(BLOCKS*BLOCK_SIZE)/1024/1024/1024,2) ARCH_GB FROM V$ARCHIVED_LOG WHERE COMPLETION_TIME > SYSDATE-7 GROUP BY TRUNC(COMPLETION_TIME) ORDER BY 1;把每天的归档量算出来,再按峰值乘以目标保留天数,就能算出一个更合理的FRA大小。比如某天峰值50G,想保留三天,至少150G。这个数字比你拍脑袋设的20G靠谱得多。
4.3 清理后如何验证,以及哪些操作不要做
清理完成后,不要急着把命令窗口关掉,多看几处确认状态。先做一次手动日志切换,模拟归档动作:
ALTER SYSTEM SWITCH LOGFILE; ALTER SYSTEM SWITCH LOGFILE;连续切换两组日志,如果都顺利归档,alert日志里不再出现ORA-00257,说明归档链路已经恢复正常。用ARCHIVE LOG LIST可以快速看当前模式:
ARCHIVE LOG LIST; Database log mode Archive Mode Automatic archival Enabled Archive destination USE_DB_RECOVERY_FILE_DEST Oldest online log sequence 1024 Next log sequence to archive 1026 Current log sequence 1050如果Archive destination后面显示的是USE_DB_RECOVERY_FILE_DEST,说明你用的是FRA而非显式目录。
另一边,有些操作在应急时千万别做。不要直接把数据库切到非归档模式,那样虽然能解除眼前的写入阻塞,但会丢失数据库的完整恢复能力,违背了开启归档的初衷。也不要在没有确认哪些归档日志尚未备份之前就盲目删掉所有归档,否则后续做时间点恢复时可能发现缺少关键日志。稳妥做法是让删除时间阈值参考最近的完整备份时间点,比如一周一备,就保留七天以上。
5. ORA-00257 的排查复盘:三个典型翻车场景
5.1 用rm直接删归档日志,备份链路全乱
现象:某生产库报ORA-00257,DBA紧张之余直接找到归档目录执行了rm -f把文件删光。数据库马上恢复写入,以为问题解决了。结果下一次RMAN备份时报“RMAN-06059: expected archived log not found”。
原因:控制文件里还记录着这些归档日志的信息,直接删文件不通知RMAN,元数据和实际文件对不上。RMAN备份时去读取这些归档日志,发现文件不存在,于是中断。
解决:这类问题只能用RMAN的CROSSCHECK ARCHIVELOG ALL重建元数据,再DELETE NOPROMPT EXPIRED ARCHIVELOG ALL清理失效记录。所以清理归档日志的唯一正确姿势是通过RMAN,而不是操作系统层面的删除。
5.2 FRA腾不出空间,是因为闪回日志一直占着
现象:FRA占用率接近100%,执行RMAN删除归档后,空间释放了一些,但依然维持在90%以上,数据库还是时不时报ORA-00257。
原因:FRA里的FLASHBACK LOG不会被归档日志清理命令删除。如果数据库开了闪回,闪回日志文件会持续累积,占用固定的空间比例。
解决:先看V$FLASH_RECOVERY_AREA_USAGE里FLASHBACK LOG的占用率。如果你不需要闪回功能,在维护窗口执行:
ALTER DATABASE FLASHBACK OFF;关闭闪回后,闪回日志会被逐步清理。如果需要保留闪回,则要单独评估FRA容量,把闪回日志的占用一并算进去。
5.3 只调大FRA不清理,第二天又堵上
现象:第一次遇到ORA-00257时,DBA直接修改DB_RECOVERY_FILE_DEST_SIZE从10G改成20G,数据库恢复正常。但第二天同一时间点又开始报错。
原因:问题的根因是归档日志积压速度过快。FRA从10G变成20G,只是多给了系统十到二十个小时的缓冲,并没有改变归档日志生成速度和备份清理速度之间的失衡。
解决:调整FRA的同时,必须同步做两件事:一是把RMAN备份策略里的归档保留时间缩短,二是配置定时清理任务。否则你只是在“治标”。这一条是很多运维踩过之后才明白的,属于典型的“今天清理明天复发”。
6. 进阶:给归档空间装上“预警机制”的落地做法
我现在的习惯是把ORA-00257当作一个可预测的周期性风险来管理,而不是等它爆发后再救火。核心手段只有两个:提前预警和自动清理。你可以把这套做法直接复用在生产环境。
预警方面,不需要额外购买监控平台,一条SQL就能解决:
SELECT ROUND(SUM(PERCENT_SPACE_USED),1) AS FRA_USED_PERCENT FROM V$FLASH_RECOVERY_AREA_USAGE;当这个值超过80时,就该人为介入;超过90,基本等价于在“裸奔”。再用一条SQL看归档日志的生成速率:
SELECT ROUND(SUM(BLOCKS*BLOCK_SIZE)/1024/1024/1024,2) AS GB_PER_DAY FROM V$ARCHIVED_LOG WHERE COMPLETION_TIME > SYSDATE - 1;如果单日归档量已经超过FRA上限的三分之一,你在加FRA之前要先想清楚:是保留策略该收敛,还是业务变更导致日志暴增。
自动清理方面,我每天会在固定时间跑一次RMAN清理脚本:
#!/bin/bash export ORACLE_SID=PROD01 export ORACLE_HOME=/u01/app/oracle/product/19.0.0/dbhome rman target / <<EOF DELETE NOPROMPT ARCHIVELOG ALL COMPLETED BEFORE 'SYSDATE-2'; CROSSCHECK ARCHIVELOG ALL; DELETE NOPROMPT EXPIRED ARCHIVELOG ALL; EOF脚本里保留两天的归档,配合每周全量备份已经足够应对绝大多数恢复场景。第一天的日志留给备份窗口,第二天的日志防止备份任务延后,超过两天的日志在每天凌晨清理。脚本加入crontab,设定在备份完成后执行,避开业务高峰。日志重定向到文件,方便第二天早晨检查。
这套机制跑下来,我已经大半年没再遇到ORA-00257。偶尔看到FRA使用率冲到75%以上,也会有足够的缓冲时间去调整。如果你现在还靠人工巡检来防这个错误,我劝你尽早把清理动作交给RMAN脚本,把预警SQL加进值班检查项里。数据库不会给人留情面,等到归档全堵,连执行诊断SQL的会话都会受影响。希望这次写下的排查路径和踩坑清单能帮到你,让以后遇到ORA-00257时少走几步弯路。
本文还有配套的精品资源,点击获取