Oracle 11g RAC 异机恢复实战(漫画版)
前言
节后刚到公司,业务那边就来了一个需求:有一套测试库的数据太老了,需要从生产库恢复一份数据过去。
生产库和测试库都是 Oracle 11g RAC,准备使用 RMAN DUPLICATE 完成恢复。原本以为很简单,就是清理旧库、恢复数据、配置 RAC,没想到过程中还是遇到了几个问题:
- RMAN DUPLICATE 成功后,修改参数时报 ORA-01565,找不到 SPFILE;
- RAC 第二节点启动后一直停留在 STARTED 状态;
- 登录第二节点时,又遇到了 ORA-09925 报错。
好在最后都解决了,两个实例正常 OPEN,完整启停测试也顺利通过。
这类生产库恢复到测试环境的需求应该挺常见,索性就把这次从旧库清理、RMAN 恢复到 RAC 重建的完整操作过程记录下来,方便以后遇到类似需求时直接参考。
一、环境及恢复方案
先看一下环境:
| 项目 | 源端生产库 | 目标测试库 |
|---|---|---|
| Oracle 版本 | 11.2.0.4 | 11.2.0.4 |
| 数据库架构 | 双节点 RAC | 双节点 RAC |
| DB_NAME | PRODDB | PRODDB |
| DB_UNIQUE_NAME | proddb | testdb |
| 实例名称 | proddb1 / proddb2 | testdb1 / testdb2 |
| 节点名称 | 生产 RAC 节点 | rac-test01 / rac-test02 |
| 数据存储 | ASM | +DATA |
| FRA | ASM | +FRA |
| 恢复方式 | RMAN 备份 | Backup-Based DUPLICATE |
目标端 Oracle Home:
/u01/app/oracle/product/11.2.0/dbhome_1
RMAN 备份目录:
/backup/rman
本次采用 Backup-Based DUPLICATE,直接使用已有的 RMAN 备份恢复,不需要连接生产库。
主要分为三个步骤:
- 清理原测试库,保留现有 RAC 和 ASM 环境。
- 执行 RMAN DUPLICATE,先恢复为单实例数据库。
- 配置 RAC 参数及 Clusterware,恢复双节点运行。


源端和目标端的 DB_NAME 均为 PRODDB,目标端使用独立的 DB_UNIQUE_NAME:testdb。
二、恢复前检查
1. 检查 RMAN 备份目录
这套生产库的 RMAN 备份是通过 NFS 挂载到目标服务器作为存储,先检查:
df -h /backup/rman
mount | grep /backup
ls -ld /backup/rman
ls -lh /backup/rman | head
确认 Oracle 用户可以正常读取备份文件,并检查数据文件、控制文件及归档日志备份是否齐全。

如果可以连接源库,可通过 RMAN 查看备份信息:
LIST BACKUP SUMMARY;
LIST BACKUP OF DATABASE;
LIST BACKUP OF ARCHIVELOG ALL;
本次使用 Level 0 备份,结合归档日志恢复,最终恢复至 SCN 73594150946。
2. 检查目标 RAC 集群
首先确认目标 RAC 环境正常,使用 grid 用户执行:
crsctl stat res -t
重点检查 ASM、监听、VIP、SCAN 等资源,再检查 ASM 磁盘组:
asmcmd lsdg
确认 +DATA、+FRA 正常挂载,并且有足够的可用空间,需要注意:ASM 磁盘组的 Free_MB 不一定等于实际可用空间,特别是 NORMAL、HIGH 冗余磁盘组,还要关注 Usable_file_MB。

接着查看当前 Clusterware 中注册的数据库:
srvctl config database
如果已经存在 testdb,还需要进一步检查:
srvctl config database -d testdb -a
srvctl status database -d testdb
srvctl config service -d testdb
这次目标端原本就有一套测试数据库,所以不能直接启动 DUPLICATE,必须先处理旧数据库。
3. 检查 Oracle 软件环境
两个节点都要确认 Oracle Home 和软件版本:
echo $ORACLE_HOME
echo $ORACLE_SID
which sqlplus
which rman
sqlplus -v
本次使用 Oracle 11.2.0.4,恢复阶段先在第一个节点操作:
export ORACLE_HOME=/u01/app/oracle/product/11.2.0/dbhome_1
export ORACLE_SID=testdb1
export PATH=$ORACLE_HOME/bin:$PATH
第二节点后续使用:
export ORACLE_SID=testdb2
三、清理原测试数据库
目标端已有一套测试 RAC,本次需要使用生产数据重新恢复,因此需要先清理原测试库,保留现有 GI、ASM 和监听环境,再执行 RMAN DUPLICATE。
1. 保存原数据库信息
先连接旧测试数据库:
sqlplus / as sysdba
检查数据库身份:
SELECT name,
db_unique_name,
dbid,
open_mode
FROM v$database;
检查 RAC 实例:
SELECT inst_id,
instance_name,
host_name,
status
FROM gv$instance
ORDER BY inst_id;
保存 SPFILE 和控制文件位置:
SHOW PARAMETER spfile;
SHOW PARAMETER control_files;
查询数据文件:
SELECT file#, name
FROM v$datafile
ORDER BY file#;
查询临时文件:
SELECT file#, name
FROM v$tempfile
ORDER BY file#;
查询 REDO:
SELECT group#, member
FROM v$logfile
ORDER BY group#;
提前记录原测试库的数据文件、控制文件和 REDO 路径,方便后续清理 ASM 文件时核对,避免误删其他数据库文件。

2. 备份原测试库配置
先导出参数文件:
CREATE PFILE='/home/oracle/init_testdb_before_rebuild.ora'
FROM SPFILE;
再保存 Clusterware 配置:
srvctl config database -d testdb -a \
> /home/oracle/testdb_srvctl_before_rebuild.txt
如果原测试库的数据还需要保留,应提前做好备份,避免清理后无法恢复。
3. 停止原测试数据库
确认旧测试库已停用、数据允许覆盖后,停止数据库:
srvctl stop database -d testdb -o immediate
检查:
srvctl status database -d testdb
确认两个实例均已停止:
Instance testdb1 is not running on node rac-test01
Instance testdb2 is not running on node rac-test02
两个节点分别检查 PMON 进程:
ps -ef | grep '[p]mon'

确认原实例已退出。
4. 注销旧 Clusterware 资源
注销旧数据库的 Clusterware 资源:
srvctl remove database -d testdb
srvctl config database

确认 testdb 已注销。注意,srvctl remove database 不会删除 ASM 中的数据文件。
5. 检查并清理 ASM 文件
使用 grid 用户:
asmcmd lsdg
asmcmd ls +DATA/
asmcmd ls +FRA/
查看旧数据库目录:
asmcmd ls -l +DATA/TESTDB/
asmcmd ls -l +FRA/TESTDB/
结合前面记录的控制文件、数据文件和 REDO 路径,逐一核对待清理文件的归属。
确认文件已废弃且没有其他资源引用后,再执行:
asmcmd rm <已确认废弃文件的完整ASM路径>

清理 ASM 文件前,建议先确认好文件的归属,避免误删。也可以根据实际情况使用 RMAN DROP DATABASE 删除旧库,但要确保不影响现有 GI、ASM、监听、VIP 和 SCAN 等集群资源。
6. 清理旧实例本地配置
两个节点分别检查:
ls -l $ORACLE_HOME/dbs/*testdb*
主要关注:
inittestdb1.ora
inittestdb2.ora
spfiletestdb1.ora
orapwtestdb1
orapwtestdb2
先备份旧配置:
mkdir -p /home/oracle/testdb_old_config
将旧 PFILE、SPFILE 和密码文件移入备份目录,核实后再清理原文件。
清理完成后,再确认:
srvctl config database
crsctl stat res -t
asmcmd lsdg
确认旧库已清理,GI 和 ASM 正常,准备恢复。
四、准备 RMAN 辅助实例
在第一个节点准备 RMAN 辅助实例,恢复阶段暂不启用 RAC。

1. 创建 PFILE
使用 oracle 用户:
export ORACLE_HOME=/u01/app/oracle/product/11.2.0/dbhome_1
export ORACLE_SID=testdb1
export PATH=$ORACLE_HOME/bin:$PATH
创建初始化参数文件:
vi $ORACLE_HOME/dbs/inittestdb1.ora
## 写入以下内容
db_name='PRODDB'
db_unique_name='testdb'
instance_name='testdb1'
cluster_database=FALSE
db_create_file_dest='+DATA'
db_recovery_file_dest='+FRA'
db_recovery_file_dest_size=100G
diagnostic_dest='/u01/app/oracle'
audit_file_dest='/u01/app/oracle/admin/testdb/adump'
job_queue_processes=0
以上为参考参数,FRA 大小、内存及兼容性参数按实际环境调整;db_name 必须与源库备份一致。
2. 创建审计目录
mkdir -p /u01/app/oracle/admin/testdb/adump
chmod 750 /u01/app/oracle/admin/testdb/adump
两个节点都需要创建审计目录,后面遇到的 ORA-09925 就与此有关。
3. 启动 NOMOUNT
sqlplus / as sysdba
执行:
STARTUP NOMOUNT
PFILE='/u01/app/oracle/product/11.2.0/dbhome_1/dbs/inittestdb1.ora';
检查:
SELECT instance_name, status
FROM v$instance;
INSTANCE_NAME STATUS
------------- -------
testdb1 STARTED
辅助实例处于 STARTED(NOMOUNT)即可,后续由 RMAN 完成恢复。
五、执行 RMAN DUPLICATE
这里采用 Backup-Based DUPLICATE,直接通过 RMAN 备份恢复,无需连接生产库。
1. 确认备份和恢复目标
恢复前确认备份目录、源库 DBID、数据文件及控制文件路径,以及归档日志和目标恢复 SCN。
本次分配 4 个辅助通道,共恢复 59 个数据文件,最终恢复至 SCN 73594150946,并通过 RESETLOGS 打开数据库。
2. 准备 RMAN 脚本
以下为 RMAN DUPLICATE 参考脚本,实际执行时需根据备份信息、ASM 路径和目标恢复 SCN 调整。
先通过辅助实例连接 RMAN:
rman auxiliary /
参考脚本:
RUN {
ALLOCATE AUXILIARY CHANNEL a1 DEVICE TYPE DISK;
ALLOCATE AUXILIARY CHANNEL a2 DEVICE TYPE DISK;
ALLOCATE AUXILIARY CHANNEL a3 DEVICE TYPE DISK;
ALLOCATE AUXILIARY CHANNEL a4 DEVICE TYPE DISK;
DUPLICATE DATABASE 'PRODDB' DBID 1234567890
TO 'PRODDB'
BACKUP LOCATION '/backup/rman'
NOFILENAMECHECK;
RELEASE CHANNEL a1;
RELEASE CHANNEL a2;
RELEASE CHANNEL a3;
RELEASE CHANNEL a4;
}
该脚本仅供参考,实际执行前需确认 RMAN 语法、ASM 文件路径及恢复 SCN,避免覆盖其他数据库文件。
3. 执行恢复
将 RMAN 脚本保存为:
/home/oracle/duplicate_testdb.rman
执行:
rman auxiliary / \
cmdfile=/home/oracle/duplicate_testdb.rman \
log=/home/oracle/duplicate_testdb.log
查看恢复日志:
tail -f /home/oracle/duplicate_testdb.log
重点查看数据文件恢复、归档应用及 RESETLOGS 是否成功。
RMAN 日志显示:
database opened
Finished Duplicate Db
Recovery Manager complete.

DUPLICATE 完成。
4. 检查恢复结果
SELECT name,
db_unique_name,
dbid,
open_mode,
database_role,
resetlogs_time
FROM v$database;
NAME DB_UNIQUE_NAME OPEN_MODE DATABASE_ROLE
-------- -------------- ---------- -------------
PRODDB testdb READ WRITE PRIMARY
确认目标库 DBID 已更新,再检查数据文件:
SELECT file#, name, status
FROM v$datafile
ORDER BY file#;

确认数据文件已恢复至目标 ASM,接下来配置双节点 RAC。
六、处理 SPFILE 丢失问题
恢复完成后,准备修改 RAC 参数:
ALTER SYSTEM SET cluster_database=TRUE SCOPE=SPFILE SID='*';
结果报错:
ORA-01565: error in identifying file
ORA-27037: unable to obtain file status
Linux-x86_64 Error: 2: No such file or directory
检查:
SHOW PARAMETER spfile;
发现当前实例引用的仍然是本地 SPFILE:
/u01/app/oracle/product/11.2.0/dbhome_1/dbs/spfiletestdb1.ora
但是操作系统上已经没有这个文件:
ls -l $ORACLE_HOME/dbs/*testdb*
实例虽然已经 OPEN,但引用的 SPFILE 文件不存在,导致无法写入参数。

重新创建 ASM 共享 SPFILE:
CREATE SPFILE='+DATA/TESTDB/spfiletestdb.ora' FROM MEMORY;
File created.
检查 ASM:
asmcmd ls -l +DATA/TESTDB/spfiletestdb.ora
在两个节点分别配置 PFILE,指向共享 ASM SPFILE。
rac-test01:
cat > $ORACLE_HOME/dbs/inittestdb1.ora <<'EOF'
SPFILE='+DATA/TESTDB/spfiletestdb.ora'
EOF
rac-test02:
cat > $ORACLE_HOME/dbs/inittestdb2.ora <<'EOF'
SPFILE='+DATA/TESTDB/spfiletestdb.ora'
EOF
新 SPFILE 不会自动生效,重启第一个实例:
SHUTDOWN IMMEDIATE;
STARTUP;
再次检查:
SHOW PARAMETER spfile;
确认已经指向:
+DATA/TESTDB/spfiletestdb.ora
确认 SPFILE 已切换。
七、配置双节点 RAC 参数
接下来配置 RAC 参数。

1. 配置集群参数
ALTER SYSTEM SET cluster_database=TRUE SCOPE=SPFILE SID='*';
ALTER SYSTEM SET cluster_database_instances=2 SCOPE=SPFILE SID='*';
2. 配置实例编号
ALTER SYSTEM SET instance_number=1 SCOPE=SPFILE SID='testdb1';
ALTER SYSTEM SET instance_number=2 SCOPE=SPFILE SID='testdb2';
3. 配置 REDO Thread
ALTER SYSTEM SET thread=1 SCOPE=SPFILE SID='testdb1';
ALTER SYSTEM SET thread=2 SCOPE=SPFILE SID='testdb2';
4. 配置 UNDO
ALTER SYSTEM SET undo_tablespace='UNDOTBS1' SCOPE=SPFILE SID='testdb1';
ALTER SYSTEM SET undo_tablespace='UNDOTBS2' SCOPE=SPFILE SID='testdb2';
5. 禁用自动任务
由于数据库来自生产环境,暂时不允许自动执行原生产库的任务:
ALTER SYSTEM SET job_queue_processes=0 SCOPE=SPFILE SID='*';
6. 清理遗留参数
检查:
SELECT sid, name, value
FROM v$spparameter
WHERE name IN (
'cluster_database',
'cluster_database_instances',
'instance_name',
'instance_number',
'thread',
'undo_tablespace',
'job_queue_processes'
)
AND isspecified = 'TRUE'
ORDER BY name, sid;
*.instance_name = testdb1
恢复阶段遗留了全局 instance_name,需要清理,避免第二节点继承。
执行:
ALTER SYSTEM RESET instance_name SCOPE=SPFILE SID='*';
同时清理全局 UNDO 参数:
ALTER SYSTEM RESET undo_tablespace SCOPE=SPFILE SID='*';
最终保留实例级配置:
*.cluster_database TRUE
*.cluster_database_instances 2
testdb1.instance_number 1
testdb2.instance_number 2
testdb1.thread 1
testdb2.thread 2
testdb1.undo_tablespace UNDOTBS1
testdb2.undo_tablespace UNDOTBS2
*.job_queue_processes 0
7. 检查 REDO 和 UNDO

先检查 REDO:
SELECT group#,
thread#,
bytes/1024/1024 mb,
status
FROM v$log
ORDER BY thread#, group#;
本次两个 Thread 均已配置,每个 Thread 5 组 REDO,每组 300MB。
检查:
SELECT thread#, status, enabled
FROM v$thread
ORDER BY thread#;
第二节点尚未启动时,Thread 2 可能显示 CLOSED。
再检查 UNDO:
SELECT tablespace_name, status
FROM dba_tablespaces
WHERE contents='UNDO';
本次 REDO 和两个 UNDO 表空间均已存在,无需重新创建。
八、准备密码文件并注册 Clusterware
1. 准备密码文件

两个节点分别需要:
rac-test01: $ORACLE_HOME/dbs/orapwtestdb1
rac-test02: $ORACLE_HOME/dbs/orapwtestdb2
使用 orapwd 创建密码文件,密码应与目标数据库 SYS 密码一致。
Oracle 11g 环境可以使用:
orapwd file=$ORACLE_HOME/dbs/orapwtestdb1
设置 SYS 密码后,将密码文件复制到第二节点并调整文件名,确保两个节点保持一致。
2. 注册数据库

使用 oracle 用户执行:
srvctl add database \
-d testdb \
-o /u01/app/oracle/product/11.2.0/dbhome_1 \
-p +DATA/TESTDB/spfiletestdb.ora \
-r PRIMARY \
-s OPEN
注册实例:
srvctl add instance -d testdb -i testdb1 -n rac-test01
srvctl add instance -d testdb -i testdb2 -n rac-test02
添加 ASM 磁盘组依赖:
srvctl modify database -d testdb -a "DATA,FRA"
检查:
srvctl config database -d testdb -a
确认:
Database unique name: testdb
Spfile: +DATA/TESTDB/spfiletestdb.ora
Database instances: testdb1,testdb2
Disk Groups: DATA,FRA
Type: RAC
Database is enabled
3. 启动 RAC

先确保手工启动的实例已经关闭:
SHUTDOWN IMMEDIATE;
然后通过 Clusterware 启动:
srvctl start database -d testdb
检查:
srvctl status database -d testdb
Instance testdb1 is running on node rac-test01
Instance testdb2 is running on node rac-test02
继续检查实例状态。
九、第二节点启动后停留在 STARTED

虽然 srvctl 显示两个实例都在运行,但进一步检查:
SELECT inst_id,
instance_name,
host_name,
status,
thread#
FROM gv$instance
ORDER BY inst_id;
INST_ID INSTANCE_NAME HOST_NAME STATUS THREAD#
------- ------------- ---------- ------- -------
1 testdb1 rac-test01 OPEN 1
2 testdb2 rac-test02 STARTED 0
第二节点仍停留在 STARTED。srvctl 显示 running,不代表实例已经 OPEN,继续登录第二节点检查。
export ORACLE_SID=testdb2
sqlplus / as sysdba
ORA-09925: Unable to create audit trail file
Linux-x86_64 Error: 2: No such file or directory
先检查磁盘:
df -h
磁盘空间正常,继续看报错:
No such file or directory
优先检查目录是否存在。
回到第一个节点查询:
SHOW PARAMETER audit_file_dest;
发现审计目录:
/u01/app/oracle/admin/testdb/adump
到第二节点检查:
ls -ld /u01/app/oracle/admin/testdb/adump
目录不存在,补齐:
创建目录:
mkdir -p /u01/app/oracle/admin/testdb/adump
chmod 750 /u01/app/oracle/admin/testdb/adump
确保目录属于 Oracle 软件用户。
重新连接数据库:
sqlplus / as sysdba
连接恢复正常,继续执行:
ALTER DATABASE MOUNT;
ALTER DATABASE OPEN;
执行成功。
再查:
SELECT inst_id, instance_name, status, thread#
FROM gv$instance
ORDER BY inst_id;
INST_ID INSTANCE_NAME STATUS THREAD#
------- ------------- ------ -------
1 testdb1 OPEN 1
2 testdb2 OPEN 2
第二节点正常 OPEN,问题原因是审计目录缺失。
十、数据库最终验收
两个实例 OPEN 后,进行验收检查。

1. 检查数据库身份
SELECT name,
db_unique_name,
dbid,
open_mode,
database_role
FROM v$database;
确认数据库名称、DBID、打开状态和角色正确。
2. 检查 RAC 实例
SELECT inst_id,
instance_name,
host_name,
status,
thread#
FROM gv$instance
ORDER BY inst_id;
两个实例均为 OPEN,分别使用 Thread 1 和 Thread 2。
3. 检查数据文件
SELECT status, COUNT(*)
FROM v$datafile
GROUP BY status;
STATUS COUNT(*)
-------- --------
ONLINE 58
SYSTEM 1
SYSTEM 为数据文件状态,属于正常结果。
4. 检查表空间
SELECT tablespace_name, status
FROM dba_tablespaces
ORDER BY tablespace_name;
34 个表空间全部 ONLINE。
5. 检查数据库组件
SELECT comp_name, status
FROM dba_registry
WHERE status <> 'VALID';
no rows selected
6. 检查监听
两个节点分别执行:
lsnrctl services
确认两个实例都注册到本地监听,并且状态为 READY。
再检查 SCAN:
srvctl config scan
srvctl status scan_listener
本地监听和 SCAN Listener 均正常,后续还需验证 SCAN 服务注册及客户端连接。
7. 完整启停测试
最后再做一次完整启停:
srvctl stop database -d testdb -o immediate
检查:
srvctl status database -d testdb
两个实例均已停止。
然后重新启动:
srvctl start database -d testdb
再次检查:
srvctl status database -d testdb
两个实例均显示 running。
登录数据库:
SELECT inst_id, instance_name, status, thread#
FROM gv$instance
ORDER BY inst_id;
INST_ID INSTANCE_NAME STATUS THREAD#
------- ------------- ------ -------
1 testdb1 OPEN 1
2 testdb2 OPEN 2
完整启停通过,两个实例均由 Clusterware 正常管理。
十一、测试环境隔离
生产库复制到测试环境后,还要检查 DB Link、定时任务和外部接口,避免误连生产系统。

先检查 DB Link:
SELECT owner, db_link, username, host
FROM dba_db_links;
这次发现测试库仍然存在连接外部数据库的 DB Link。
连接地址已脱敏,需确认是否指向生产环境。
检查 Scheduler Job:
SELECT owner, job_name, enabled, state
FROM dba_scheduler_jobs
WHERE enabled = 'TRUE';
还发现了多个已启用任务,其中包含业务相关任务。
再检查 DBMS_JOB:
SELECT schema_user, job, broken, what
FROM dba_jobs
ORDER BY schema_user, job;
因此暂时保持:
ALTER SYSTEM SET job_queue_processes=0 SCOPE=BOTH SID='*';
完成环境隔离检查前,暂不启用这些任务。
总结
本次恢复从清理原测试库开始,依次完成 RMAN DUPLICATE、共享 SPFILE 创建、RAC 参数配置及 Clusterware 注册,最终恢复双节点 RAC。
RMAN 共恢复 59 个数据文件,过程中主要遇到两个问题:
- ORA-01565:恢复完成后,原 SPFILE 文件不存在,导致参数修改失败。通过
CREATE SPFILE FROM MEMORY重新创建共享 ASM SPFILE,重启后恢复正常。 - ORA-09925:第二节点启动后停留在 STARTED,排查发现
audit_file_dest目录不存在,创建目录后正常 MOUNT、OPEN。
最后通过 srvctl 完成双节点启停验证,两个实例均正常 OPEN。

这次恢复也算再次验证了一点:RMAN DUPLICATE 完成不代表整个恢复结束,后续的 RAC 配置、监听检查和测试环境隔离同样不能少。
- 点赞
- 收藏
- 关注作者
评论(0)