说明
此恢复测试脚本,基于rman备份脚本文章使用的fullbak.sh做的备份。
数据库将被恢复到RESTORE_LO参数设置的位置。
在恢复完成后,执行一个测试sql,确认数据库恢复完成,数据库备份是好的。恢复测试数据库的参数,比如SGA大小都没有优化,没有设置值。如果需要用于其他测试,可能需要适当调整。
主要步骤:
先建立一个init文件,只包含数据库名,版本号,和一个控制文件位置,用它启动到nomount, 从autobackup恢复控制文件。 用这个控制文件启动到mount,进行数据库恢复。在打开前,修改日志名字到RESTORE_LO指定位置。
1. 检查当前备份
ls /u02/rmanbackup
得到自动备份文件名如下图。记录其自动备份的编号,第一次备份是00.
查看备份日志,得到DBID.
*[oracle@testdb1 rmanbackup]$ grep DBID logs/rman_full_2025-05-29-1547.log
connected to target database: RISK (DBID=3842787173)
[oracle@testdb1 rmanbackup]$*
2. 修改恢复测试脚本
根据上述信息修改恢复脚本。
数据库ORACLE_SID, DBID,备份日期, 测试时数据库恢复使用的目录 /u02/testdata
如果目录不存在,先手动建立。
mkdir /u02/testdata
对于第一次运行,需要根据实际环境设置,以后基本不需要修改。
3 关闭数据库并mv当前的spfile(如果不是在同一个服务器恢复,此步可以忽略)
如果在当前服务器恢复(不建议这么做,建议在其他服务器测试)。需要先停止数据库。并且把当前使用的spfile改名(备份,并防止测试时用它)。
sqlplus / as sysdba
shut immediate;
cd $ORACLE_HOME/dbs
mv spfile${ORACLE_SID}.ora spfile${ORACLE_SID}.ora.def
输出
SQL> shut immediate
Database closed.
Database dismounted.
ORACLE instance shut down.
SQL> exit
Disconnected from Oracle Database 11g Enterprise Edition Release 11.2.0.4.0 - 64bit Production
With the Partitioning, OLAP, Data Mining and Real Application Testing options
[oracle@testdb1 scripts]$ cd $ORACLE_HOME/dbs
[oracle@testdb1 dbs]$ ls -l *risk*
-rw-r----- 1 oracle oinstall 11681792 Apr 11 16:01 cntrlrisk.dbf
-rw-rw---- 1 oracle oinstall 1544 May 29 15:59 hc_risk.dat
-rw-r--r-- 1 oracle oinstall 376 Apr 12 22:00 initrisk.ora
-rw-r--r-- 1 oracle oinstall 83 Apr 12 21:59 initrisk.ora.0412
-rw-r----- 1 oracle oinstall 1536 Apr 22 09:50 orapwrisk
-rw-r----- 1 oracle oinstall 12369920 May 29 15:49 snapcf_risk.f
-rw-r----- 1 oracle oinstall 2560 May 29 05:45 spfilerisk.ora
[oracle@testdb1 dbs]$ mv spfilerisk.ora spfilerisk.ora.def
[oracle@testdb1 dbs]$ ls spfile*
spfilerisk.ora.def
[oracle@testdb1 dbs]$
4. 执行恢复
./auto_rman_test.sh
输出:
[oracle@testdb1 scripts]$ ps -ef|grep pmon
oracle 4181 2779 0 16:04 pts/0 00:00:00 grep --color=auto pmon
[oracle@testdb1 scripts]$ env|grep SID
ORACLE_SID=risk
[oracle@testdb1 scripts]$ vi auto_rman_test.sh
[oracle@testdb1 scripts]$ clear
[oracle@testdb1 scripts]$ cat auto_rman_test.sh
#!/bin/sh
#########################
# desc: test rman backup to be restored.
# set ORACLE_SID,ORACLE_HOME.
# RMANBAK_LOC: the rman backup is located. it must be same as primary db.
# RESTORE_LOC: the rmanbackup will be restored to.
# TESTSQL: the sql to be tested.
# DBID: the database ID.
# 2020.11.15. v0.1
# update: 2022.12.29 20:00
# update: 2023.01.03. 主库的在线日志目录要在备库上也创建.日志文件将在这个目录创建.并授予oracle读写权限.否则reset logs失败.
# update: 2023.02.11 增加了until的条件.可以设置时间或者sequence.
# update: 2025.05.17. 如果在原来服务器测试, 需要在测试前,把spfile文件改名。否则会覆盖以前的控制文件。
############################# 参数设置#################
export ORACLE_HOME=/u01/app/oracle/product/11.2.0/db_1
export ORACLE_SID=risk
export DBID="3842787173"
export RMANBAK_LOC="/u02/rmanbackup" #主库rman备份目录, 必须和主库备份目录相同.
export RESTORE_LOC="/u02/testdata" #恢复到指定目录
export BACKUP_DATE="20250529" #数据库备份的时间,用来设置自动备份的控制文件名字,当天是`date +%Y%m%d`
export TESTSQL="select count(*) from dba_tables;"
#export TESTSQL="select * from settlement.t_systemstatus"
#export UNTILTIME="`date +%Y-%m-%d` 03:00:00" #恢复的untiltime, 可以是主库开始备份的时间,或指定时间,如下
#export UNTILTIME="2023-12-29 17:43:00"
#export UNTILSEQ=851
#export UNTILTIME=""
#############局部变量
LOGFILE=/tmp/rman_recovery_`date +%Y%m%d-%H%M`.log
SQLLOG=/tmp/sqlplus_recovery_`date +%Y%m%d-%H%M`.log
MOUNTCMD=/tmp/mount.cmd
RECVCMD=/tmp/recv.cmd
#conrolfile控制文件名字格式, rman设置自动备份控制文件格式为 auto_%T_%F.%d
UPPER_SID=`echo $ORACLE_SID | tr '[:lower:]' '[:upper:]'`
CONTROLFILE=$RMANBAK_LOC/auto_${BACKUP_DATE}_c-$DBID-${BACKUP_DATE}-00.${UPPER_SID}
echo $CONTROLFILE
if [ ! -d ${RESTORE_LOC}/${ORACLE_SID} ]; then
mkdir -p ${RESTORE_LOC}/${ORACLE_SID}
fi
cat >$ORACLE_HOME/dbs/init${ORACLE_SID}.ora<<EOF
db_name=${ORACLE_SID}
control_files=${RESTORE_LOC}/${ORACLE_SID}/contorl01.ctl
compatible='11.2.0.4.0'
EOF
#启动nomount
$ORACLE_HOME/bin/sqlplus -s / as sysdba <<EOF
startup force nomount;
exit;
EOF
#创建恢复控制文件脚本
cat > $MOUNTCMD <<EOF
run{
restore controlfile from "$CONTROLFILE";
sql 'alter database mount';
}
EOF
#恢复控制文件并mount
$ORACLE_HOME/bin/rman target / cmdfile $MOUNTCMD
if [ $? != 0 ]; then
echo "error mount"
exit 1;
fi
#设置until条件
echo -e "untiltime is : $UNTILTIME"
if [ ${#UNTILTIME} -gt 0 ]; then #没有指定恢复时间
UNTIL_CON="set until time '$UNTILTIME';"
elif [ ${#UNTILSEQ} -gt 0 ]; then
UNTIL_CON="set until sequence $UNTILSEQ;"
else
UNTIL_CON=""
fi
echo $UNTIL_CON
cat > $RECVCMD <<EOF
run{
catalog start with "$RMANBAK_LOC" noprompt;
crosscheck backup;
crosscheck archivelog all;
delete noprompt expired backup;
delete noprompt expired archivelog all;
sql "alter session set nls_date_format=''yyyy-mm-dd hh24:mi:ss''";
$UNTIL_CON
set newname for database to '$RESTORE_LOC/$ORACLE_SID/%U';
restore database;
switch datafile all;
switch tempfile all;
recover database;
}
EOF
if [ ! -d /tmp/log ]; then
mkdir /tmp/log
fi
mv /tmp/*.log /tmp/log
$ORACLE_HOME/bin/rman target / cmdfile $RECVCMD >$LOGFILE
#change online redo log to new location
# 新的目标目录前缀
REDO_LOC="${RESTORE_LOC}/${ORACLE_SID}"
# 输出 SQL 文件
SQL_SCRIPT="rename_redo.sql"
> "$SQL_SCRIPT" # 清空/新建文件
# 从数据库读取 redo 路径并生成 SQL
sqlplus -s / as sysdba <<EOF | grep "^/" | while read -r old_path
SET HEADING OFF
SET FEEDBACK OFF
SET PAGESIZE 0
SET TRIMSPOOL ON
SELECT MEMBER FROM V\$LOGFILE;
EXIT
EOF
do
filename=$(basename "$old_path")
new_path="${REDO_LOC}/${filename}"
echo "ALTER DATABASE RENAME FILE '$old_path' TO '$new_path';" >> "$SQL_SCRIPT"
done
sqlplus -s / as sysdba <<EOF
SET HEADING OFF
SET FEEDBACK OFF
SET PAGESIZE 0
SPOOL clear_redo.sql
SELECT 'ALTER DATABASE CLEAR LOGFILE GROUP ' || GROUP# || ';'
FROM V\$LOG
ORDER BY GROUP#;
SPOOL OFF
EOF
$ORACLE_HOME/bin/sqlplus -s <<EOF >$SQLLOG
conn / as sysdba
start rename_redo.sql
start clear_redo.sql
alter database open resetlogs;
$TESTSQL
exit;
EOF
more $SQLLOG
[oracle@testdb1 scripts]$ ./auto_rman_test.sh
/u02/rmanbackup/auto_20250529_c-3842787173-20250529-00.RISK
ORACLE instance started.
Total System Global Area 229683200 bytes
Fixed Size 2251936 bytes
Variable Size 171967328 bytes
Database Buffers 50331648 bytes
Redo Buffers 5132288 bytes
Recovery Manager: Release 11.2.0.4.0 - Production on Thu May 29 16:04:57 2025
Copyright (c) 1982, 2011, Oracle and/or its affiliates. All rights reserved.
connected to target database: RISK (not mounted)
RMAN> run{
2> restore controlfile from "/u02/rmanbackup/auto_20250529_c-3842787173-20250529-00.RISK";
3> sql 'alter database mount';
4> }
5>
Starting restore at 29-MAY-25
using target database control file instead of recovery catalog
allocated channel: ORA_DISK_1
channel ORA_DISK_1: SID=170 device type=DISK
channel ORA_DISK_1: restoring control file
channel ORA_DISK_1: restore complete, elapsed time: 00:00:01
output file name=/u02/testdata/risk/contorl01.ctl
Finished restore at 29-MAY-25
sql statement: alter database mount
released channel: ORA_DISK_1
Recovery Manager complete.
untiltime is :
mv: cannot move ‘/tmp/ntpdate.log’ to ‘/tmp/log/ntpdate.log’: Operation not permitted
ALTER DATABASE CLEAR LOGFILE GROUP 1;
ALTER DATABASE CLEAR LOGFILE GROUP 2;
ALTER DATABASE CLEAR LOGFILE GROUP 3;
ALTER DATABASE CLEAR LOGFILE GROUP 4;
ALTER DATABASE CLEAR LOGFILE GROUP 5;
ALTER DATABASE CLEAR LOGFILE GROUP 6;
ALTER DATABASE CLEAR LOGFILE GROUP 7;
Database altered.
Database altered.
Database altered.
Database altered.
Database altered.
Database altered.
Database altered.
Database altered.
Database altered.
Database altered.
Database altered.
Database altered.
Database altered.
Database altered.
Database altered.
COUNT(*)
----------
1322 =》恢复成功,执行了测试sql
[oracle@testdb1 scripts]$ cd /u02/testdata/
[oracle@testdb1 testdata]$ ls -l
total 4
drwxr-xr-x 2 oracle oinstall 4096 May 29 16:08 risk
[oracle@testdb1 testdata]$ ls risk
contorl01.ctl data_D-RISK_TS-SYSTEM_FNO-1 data_D-RISK_TS-UNDOTBS1_FNO-3 redo02.log redo05.log
data_D-RISK_TS-SOE_FNO-6 data_D-RISK_TS-TBS_SPLEX_FNO-5 data_D-RISK_TS-USERS_FNO-4 redo03.log redo06.log
data_D-RISK_TS-SYSAUX_FNO-2 data_D-RISK_TS-TEMP_FNO-1 redo01.log redo04.log redo07.log
[oracle@testdb1 testdata]$
5 测试完成后清理
恢复测试完成后,测试sql执行正常,说明备份正常。
可以清理测试库。
把测试库关闭,删除测试库文件。
如果是在同一个服务器恢复测试,测试完成后,还需要把
spfile文件mv到原来的名字。
cd $ORACLE_HOME/dbs
mv spfile${ORACLE_SID}.ora.def spfile${ORACLE_SID}.ora
6. 排错
[oracle@testdb1 scripts]$ ./auto_rman_test.sh
/u02/rmanbackup/auto_20250517_c-4230975025-20250517-10.CTP
./auto_rman_test.sh: line 43: /u01/app/oracle/product/11.2.0/dbhome_1/dbs/initctp.ora: No such file or directory
./auto_rman_test.sh: line 50: /u01/app/oracle/product/11.2.0/dbhome_1/bin/sqlplus: No such file or directory
./auto_rman_test.sh: line 64: /u01/app/oracle/product/11.2.0/dbhome_1/bin/rman: No such file or directory
error mount
[oracle@testdb1 scripts]$ env|grep HOME
ORACLE_HOME=/u01/app/oracle/product/11.2.0/db_1
[oracle@testdb1 scripts]$
分析: auto_rman_test.sh中$ORACLE_HOME设置错误。修正后重新执行正常。
7 部署自动恢复测试
数据库服务器: crontab设置把rman备份上传到测试服务器,
测试服务器: crontab设置rman自动恢复。
这样可以自动测试当天备份,确认数据库备份是可用的。