Aekor

Aekor
专注于用户阅读体验的响应式博客主题
  1. 首页
  2. Oracle 数据库
  3. 正文

Oracle 19c 启停、归档模式与 ORA-01157 处理

2026-03-01 14500点热度 0人点赞 0条评论

这三件事在运维中经常连在一起出现:维护前要按正确顺序停库停集群,做热备份前要确认归档已开启,而归档或表空间操作稍有不慎,就可能遇到数据文件路径错误导致的 ORA-01157。本文按“启停 → 归档 → 故障修复”的顺序整理,命令均取自原文的实操记录。

适用范围:Oracle 19c,RAC 部分同样适用于 11g/12c 的 CRS 管理方式;ORA-01157 的案例原文发生在 11g RAC 环境,处理思路对 19c 一致,但路径和磁盘组名要按实际替换。

一、RAC 启停顺序

原则只有一句:启动先集群后数据库,关闭先数据库后集群。顺序反了,数据库实例会先于集群资源下线,轻则报资源状态异常,重则留下未完成的实例恢复。

关闭

先以 grid 用户确认当前状态,再停数据库:

-- 查看数据库服务状态
crsctl stat res -t

-- 停数据库
srvctl stop database -d 服务名

-d 后面是数据库名,不是实例名。RAC 下这条命令会停掉所有节点上的实例,不需要逐节点执行。

数据库完全停止后,再用 root 停集群,两个节点都要操作:

-- 停集群(两个节点都操作)
/oracle/app/19.3.0/grid/bin/crsctl stop crs

两个节点之间要留出时间差。节点一停完、确认 crsctl check crs 已离线,再停节点二;同时停两个节点容易让集群在关闭过程中互相等待。停集群会连带停掉 ASM、监听和所有由 CRS 管理的资源,所以必须先确认数据库已经停干净。

启动

先起集群,仍然是两个节点都执行:

-- 启动集群(两个节点都操作)
/oracle/app/19.3.0/grid/bin/crsctl start crs

节点一启动完成后再启动节点二。集群起来后,用 grid 用户检查:

-- 检查集群状态
crsctl check crs
CRS-4638: Oracle High Availability Services is online
CRS-4537: Cluster Ready Services is online
CRS-4529: Cluster Synchronization Services is online
CRS-4533: Event Manager is online

四条都 online 才算集群正常。接着确认 ASM 和数据库进程:

-- 确认服务
ps -ef | grep smon

-- 查看数据库状态
crsctl status res -t
......
ora.testcdb.db
1   OFFLINE OFFLINE     Instance Shutdown,STABLE
2   OFFLINE OFFLINE     Instance Shutdown,STABLE

此时实例处于 Instance Shutdown,STABLE,说明集群没有自动拉起数据库,这是正常的。最后启动数据库:

-- 启动数据库
cd /oracle/app/19.3.0/grid_1/bin
srvctl start database -d 服务名

原文这里切换到 grid_1/bin 执行 srvctl,说明环境中存在多个 Grid Home 或 PATH 未包含 srvctl。如果直接执行 srvctl 报“command not found”,用绝对路径,不要以为是集群坏了。

启动后再查一次 crsctl status res -t,确认所有实例为 ONLINE、服务状态为 STABLE。

常见错误

  • 只停了一个节点的实例就停集群:另一个节点上的实例会被强制终止,需要实例恢复。
  • 先停集群再停数据库:srvctl stop database 失去 CRS 支撑,可能挂起。
  • 启动时只起了一个节点的 CRS 就起库:另一个节点实例起不来,或者资源状态长期 INTERMEDIATE。
  • 用 sqlplus shutdown 代替 srvctl stop database:单节点可以,RAC 下容易只停本节点,另一节点仍在运行。

启停时的两个易错点

只维护一个节点。 如果只是重启某个实例,不要停整个数据库,也不要用 shutdown immediate 在单节点操作后再手动拉起,容易和 CRS 的资源管理打架。正确做法是用 srvctl 针对实例操作,并在操作后用 crsctl status res -t 确认另一个节点未受影响。停机维护前先确认没有业务连接落在该实例上,必要时先 srvctl stop service 把服务摘走。

启停后没有验证监听。 集群起来不代表监听已经注册好。数据库启动后,用 lsnrctl status 确认实例已注册到监听,再用 tnsping 或实际连接验证。RAC 下还要确认 SCAN 监听在所有节点都正常,否则应用可能连到未注册的节点。

二、开启归档模式

归档模式是热备份的前提。Oracle 默认是非归档模式,开启操作必须在数据库 MOUNT 状态执行,不能在 OPEN 状态直接切换。

前置检查与备份

先确认当前状态:

archive log list;

再备份一份 pfile,便于参数改错时回退:

create pfile='/home/oracle/pfile1216.ora' from spfile;

这一步成本很低,但很关键。归档相关参数(db_recovery_file_dest、db_recovery_file_dest_size、log_archive_dest_1)一旦写错,数据库可能起不来,有 pfile 至少能定位原始参数。

同时确认归档空间足够。开启归档后,如果 db_recovery_file_dest_size 太小,很快会因归档写满导致数据库挂起。

操作步骤

  1. 关闭数据库。RAC 环境两个节点都要停:
shutdown immediate;
  1. 在节点一启动到 mount:
startup mount;
  1. 切换归档并打开:
alter database archivelog;
alter database open; --启动数据库,RAC的话需要双节点执行
archive log list;

alter database archivelog 只在节点一执行;alter database open 在 RAC 下需要两个节点都执行,或者直接用 srvctl start database -d 服务名 统一拉起。

  1. 调整归档空间:
show parameter db_recovery_file_dest_size;

-- 修改归档空间大小
alter system set db_recovery_file_dest_size=100G;

100G 是示例值,按实际归档保留策略和磁盘容量设置。这个参数可以在线修改,不需要重启。

  1. 确认归档目录:
show parameter recovery_file_dest;

-- 修改归档目录
# 单机路径
alter system set log_archive_dest_1='location=/oracle/app/db/archivelog' scope=both;

# RAC环境路径
alter system set db_recovery_file_dest='+ARCHDG';

单机用文件系统目录时改 log_archive_dest_1;RAC 使用 ASM 时改 db_recovery_file_dest 指向归档磁盘组。两种写法不要混用:同时设置 log_archive_dest_1 和 db_recovery_file_dest,归档可能落到非预期位置。

  1. 再次确认:
archive log list;

输出中的 Database log mode 应为 Archive Mode,Automatic archival 应为 Enabled。

归档空间与保留策略

开启归档只是第一步,能不能长期稳定运行取决于空间。查当前使用情况:

select name,space_limit/1024/1024/1024 limit_g,
       space_used/1024/1024/1024 used_g,
       space_reclaimable/1024/1024/1024 reclaim_g,
       number_of_files
from v$recovery_file_dest;

space_reclaimable 是已经被 RMAN 标记为可删除、但尚未清理的空间。它长期很大,说明备份清理策略没有生效,需要检查 RMAN 的保留策略和归档删除作业,而不是一味扩容。

查归档目标的状态和错误:

select dest_id,dest_name,status,error,binding
from v$archive_dest
where dest_id<=10;

status 为 ERROR 时,error 列会给出具体原因,常见的是空间满、路径不可写、ASM 磁盘组未挂载。归档写不进去时数据库会挂起(ARCHIVELOG 模式下 redo 无法覆盖),所以这个查询应该纳入日常监控。

如果使用 FRA(db_recovery_file_dest),还要确认 log_archive_dest_1 没有被同时设置成文件系统路径。两者同时生效时,归档可能写到非预期位置,FRA 的空间统计也会失真。

三、关闭归档模式

关闭归档的步骤与开启对称,同样要求 MOUNT 状态:

archive log list;

shutdown immediate;

startup mount;

alter database noarchivelog;
alter database open; --启动数据库,rac的话需要双节点执行
archive log list;

关闭归档前必须想清楚后果,原文列出的几点都成立:

  • 数据丢失无法回退:没有归档,只能恢复到上一次备份点。
  • 只能做逻辑备份,系统异常时仍存在数据丢失。
  • 逻辑备份需要额外的本地空间和长期保留策略,备份时间长,且影响性能。
  • 数据库坏块可能导致系统不可用,逻辑备份无法修复坏块,只能重建。

生产库不建议关闭归档。如果只是为了省空间,优先调整归档保留策略或扩容归档盘,而不是切到非归档模式。

四、ORA-01157:数据文件落在本地

现象与原因

在 RAC 环境创建表空间时,如果漏写 +DATADG,数据文件会落到本地文件系统,例如 /oracle/app/db/systemnew3.dg。本节点可能还能访问,另一个节点完全看不到这个路径,启动或访问时报:

ORA-01157: cannot identify/lock datafile

原文只记录了 01157 这一行。实际环境中通常还会跟一条 ORA-01110 指出具体文件,以告警日志和 v$datafile 的输出为准。

根因不是数据文件损坏,而是路径只在一个节点存在。所以修复方向是让所有节点通过 ASM 访问同一个文件,而不是去“恢复”文件。

三种方式按侵入性从低到高排列:ASM 拷贝改名 → RMAN switch → 重建表空间。优先用前两种,重建表空间是最后手段。

先定位是哪个文件

ORA-01157 的报错文本里通常只有文件号,没有路径。先查清楚缺的是哪个文件:

select file#,status,error,name from v$datafile order by file#;

status 为 OFFLINE 且 error 列显示 CANNOT IDENTIFY 的,就是问题文件。再用 v$recover_file 确认:

select file#,online_status,error,change#,time from v$recover_file;

如果数据库还能启动到 mount,这两个视图足够定位。如果实例已经起不来,只能看告警日志里 ORA-01157 后面的文件名。

定位之后先判断文件是否真实存在、是否可读:

ls -l /oracle/app/db/systemnew3.dg

文件存在但只有本节点可见,是本文讨论的路径问题;文件不存在或大小为 0,说明问题更严重,需要从备份恢复,不能靠 rename 解决。

方式一:asmcmd 拷贝并 rename

适用于数据文件内容完好、只是位置不对的情况。

  1. 在正常节点关闭数据库:
SQL> shutdown immediate;
  1. 用 asmcmd 把本地文件复制进 ASM:
ASMCMD> cp /oracle/app/db/systemnew3.dg .
copying /oracle/app/db/systemnew3.dg -> +DATADG/TESTCDB/DATAFILE/systemnew3.dg

ASMCMD> pwd
+DATADG/TESTCDB/DATAFILE
ASMCMD>

cp 的目标写成 .,表示复制到当前目录。执行前先 cd 到目标数据文件目录,复制完成后记下 ASM 自动生成的文件名。

  1. 启动到 mount:
SQL> startup mount
  1. 修改控制文件中的路径:
SQL>  alter database rename file '/oracle/app/db/systemnew3.dg' to '+DATADG/TESTCDB/DATAFILE/systemnew3.dg';
Database altered.
  1. 打开数据库:
SQL> alter database open;
  1. 重启验证,两个节点都要做:
shutdown immediate;
startup;

节点二同样执行 shutdown immediate 和 startup。只在节点一验证通过不算完成,必须确认节点二也能正常打开。

注意事项:rename 只改控制文件记录,不会搬文件;必须先 cp 成功,再执行 rename。顺序反了,数据库会找不到文件。复制期间数据库应处于关闭或至少该数据文件离线状态,避免文件头不一致。

变体:停集群后拷贝(原文方式二)

适用于需要确保所有节点都不持有该文件的场景。

  1. 关闭整个集群,在节点一用 grid 登录 asmcmd 复制:
ASMCMD > cp /app/oracle/11.2.0/db_1/dbs/DATADG +DATADG/NCM/DATAFILE/SYSTEM01.dbf  (DATADG是错误创建的数据文件)
copying /app/oracle/11.2.0/db_1/dbs/DATADG - > +DATADG/NCM/DATAFILE

原文这条命令的目标路径写的是 SYSTEM01.dbf,源文件却叫 DATADG,且后面的 rename 又指向 +DATADG/NCMAIL/DATAFILE/SYSTEM01.dbf。这三处名称不一致,实际执行时必须统一成真实文件名和真实目录,否则会复制出错误文件或 rename 失败。此处保留原文,供对照。

  1. 启动数据库到 mount:
srvctl start database -d NCM -o mount
  1. 修改路径:
alter database rename file '/app/oracle/11.2.0/db_1/dbs/DATADG' to '+DATADG/NCMAIL/DATAFILE/SYSTEM01.dbf';
  1. 关闭集群并正常启动,确认两个节点都能打开。

这种方式停机时间更长,但能避免“节点二仍持有本地文件句柄”的干扰。如果方式一在节点二反复报错,可以改用这种方式。

方式二:RMAN backup as copy + switch

适用于希望由 RMAN 管理文件副本、并保留备份记录的场景。核心是三步:做成映像副本、set newname、switch。

  1. 做数据文件映像副本:
RMAN> run
2> { allocate channel c1 type disk;
3>  backup as copy datafile 7 format '+DATA'; }
using target database control file instead of recovery catalog
allocated channel: c1
channel c1: SID=71 instance=ora11211 device type=DISK
Starting backup at 27-AUG-22
channel c1: starting datafile copy
input datafile file number=00007 name=/u01/app/oracle/11.2.0.4/dbs/1.test
output file name=+DATA/ora112/datafile/system.269.1113783961 tag=TAG20220827T002601 RECID=3 STAMP=1113783961
channel c1: datafile copy complete, elapsed time: 00:00:01
Finished backup at 27-AUG-22
released channel: c1

记下输出中的 output file name,下一步要用。文件号 7 是示例,按实际 file_id 替换。

  1. 设置新文件名:
RMAN>  run {  set newname for datafile 7 to '+DATA/ora112/datafile/system.269.1113783961';}
executing command: SET NEWNAME
RMAN>
  1. 切换控制文件记录到副本:
RMAN> switch datafile 7 to copy;
datafile 7 switched to datafile copy "+DATA/ora112/datafile/system.269.1113783961"

switch 之后,控制文件指向副本,原本地文件不再被引用。确认无误后再删除本地文件,不要提前删。

  1. 确认路径与容量:
set linesize 150;
col tablespace_name format a50;
select a.tablespace_name,a.bytes/1024/1024 "Sum MB",(a.bytes-b.bytes)/1024/1024 "used MB",b.bytes/1024/1024 "free MB",round(((a.bytes-b.bytes)/a.bytes)*100,2) "percent_used"
from (select tablespace_name,sum(bytes) bytes from dba_data_files group by tablespace_name) a,
(select tablespace_name,sum(bytes) bytes,max(bytes) largest from dba_free_space group by tablespace_name) b where a.tablespace_name=b.tablespace_name
order by ((a.bytes-b.bytes)/a.bytes) desc ;

set linesize 300
col tablespace_name for a30
col file_name for a80
col autoextensible for a5
select file_id,tablespace_name,file_name,bytes/1024/1024 MB,autoextensible from dba_data_files order by 1;

原文这两条查询里 groupby、orderby 写成了连写,且 orderby1 缺空格,直接执行会报错;上面按正确语法补了空格,其余字段和别名保持原样。查完确认数据文件路径已经是 ASM,再决定是否需要 resize。

如果新位置所在磁盘组空间紧张,再考虑 resize:

alter database datafile file_id resize **G;

file_id 和 **G 都要替换成实际值;缩小数据文件有下限(不能小于已用块),执行前先确认 dba_free_space。

方式三:重建表空间(最后手段)

当数据文件已经损坏、本地副本不可读,或者表空间里的数据可以从其他来源重建时,才走这条路。原文没有展开具体命令,这里只给顺序,不提供可直接执行的脚本:

  1. 确认表空间内有哪些对象、能否从其他库或历史备份补齐。
  2. 用数据泵或 CTAS 把还能读出的数据导出到临时位置。
  3. 删除原表空间(drop tablespace ... including contents and datafiles),注意这会删除文件,执行前必须确认导出完整。
  4. 用 create tablespace 在 ASM 上重建,数据文件路径写成 +DATADG。
  5. 导入数据,重建索引、约束、权限和同义词。
  6. 校验行数、索引状态和业务功能。

这条路停机时间最长,而且依赖备份或外部数据源。能通过 rename 或 switch 解决的,不要重建表空间。

方式选择

场景推荐方式
文件完好、只是路径错,停机窗口短方式一:asmcmd cp + rename
节点二反复报文件被占用方式一的变体:停集群后拷贝
希望保留 RMAN 副本记录、便于后续恢复方式二:backup as copy + switch
文件已损坏、无法读取,或数据可从别处重建方式三:重建表空间(最后手段)

重建表空间意味着导出数据、删除表空间、重建、再导入。只有在文件不可读、又没有可用备份时才考虑;它能解决问题,但代价远高于前两种。

修复后的验证

  • 两个节点分别 startup,确认都能打开,不只是在节点一验证。
  • 查 v$datafile/dba_data_files,确认所有数据文件路径都是 +DATADG 开头,没有残留本地路径。
  • 查 v$tablespace 和 dba_tablespaces,确认表空间状态为 ONLINE。
  • 做一次小范围读写测试,确认没有坏块。
  • 检查告警日志,确认没有新的 ORA-01157 或 ORA-01110。

风险提示

  • 停集群、切归档、rename 数据文件都属于高风险操作,必须在维护窗口执行,并确认已有可用备份。
  • alter database rename file 不搬文件,只改记录;先复制、后改名,顺序不能反。
  • 归档模式切换必须在 MOUNT 状态;在 OPEN 状态执行会直接报错。
  • RAC 下任何“打开数据库”的动作都要确认两个节点,单节点成功不代表集群正常。
  • 删除原本地数据文件前,先确认数据库已经用新路径正常打开并运行过一段时间。

待核对

  • ORA-01157 案例原文为 11g RAC,本文保留原路径(/oracle/app/db、/app/oracle/11.2.0),在 19c 环境需替换为实际路径。
  • 原文方式二(本文“方式一的变体”)的源文件名 DATADG、目标 SYSTEM01.dbf 与 rename 目标 NCMAIL 三处不一致,原文如此,执行前必须统一。
  • 原文方式三(本文“方式二:RMAN”)的 file_id 7、+DATA/ora112/... 为原文示例,需按实际环境替换。
  • 方式三“重建表空间”原文只给了结论,未给命令;本文仅列步骤顺序,不提供可直接执行的脚本。
  • 原文归档目录示例 /oracle/app/db/archivelog 与 +ARCHDG 分别对应单机和 RAC,不要同时设置。
  • 原文 show parameter recovery_file_dest; 按原文保留,实际参数名为 db_recovery_file_dest,执行时以 show parameter db_recovery_file_dest 为准。
  • 原文在 RAC 归档步骤中标注 alter database open 需双节点执行;RAC 下每个实例需分别启动/打开,实际以 srvctl start database 统一拉起更稳妥,此处保留原文说法。
  • 文中 v$recovery_file_dest、v$archive_dest、v$datafile/v$recover_file 查询和 srvctl stop service 的说明为补充内容,原文未涉及,用于补齐定位与验证环节。
  • 原文末尾的表空间使用率 SQL 含 groupby、orderby、orderby1 连写问题,本文按正确语法补空格后收录,字段与别名未改。

原文首发于微信公众号「止水研习社」。

本作品采用 知识共享署名 4.0 国际许可协议 进行许可
标签: Oracle 归档模式 故障处理
最后更新:2026-10-17

Aekor

这个人很懒,什么都没留下

点赞
< 上一篇
下一篇 >

文章评论

razz evil exclaim smile redface biggrin eek confused idea lol mad twisted rolleyes wink cool arrow neutral cry mrgreen drooling persevering
取消回复

使用AI教程

  • API报错解决方案
  • API 基础知识
  • API Key 获取
  • 最新接入教程

分类

  • Blog
  • Oracle 数据库
  • TradingAgents-CN
  • 使用教程
  • 数据库

COPYRIGHT © 2026 Aekor. ALL RIGHTS RESERVED.

Theme Kratos Made By Seaton Jiang