RAMN备份与还原

CentOS7.6 Oracle11.2.0.4

Posted by wangtiegang on October 20, 2019

最近新装的测试数据库需要做rman备份还原,将不同数据库实例名的备份还原到新的测试库中,顺便在新的库中设置rman备份脚本。

rman备份

关闭oracle闪回(fast_recovery_area)功能

由于在安装数据库的时候按照文档开启了闪回功能,会在rman备份时产生一些麻烦,了解了一下之后,最好是关闭闪回功能。

oracle默认将归档日志放到了闪回恢复区中,生产库上事物处理比较频繁的情况下,若是有个大的事物提交,并有频繁的日志切换的话,闪回恢复区设定的大小很快就会被用完。闪回恢复区的空间被占满了以后,很严重的后果就是,无法再归档了,整个数据库就会不可用,将直接影响生产系统的运行,直到你增大闪回恢复区或转移/删除闪回恢复区里的归档日志,清理出足够空间来继续进行归档为止。

检查是否开启闪回:

select flashback_on from v$database;

关闭闪回:

1
2
3
4
SQL> shutdown immediate;
SQL> startup mount;
SQL> alter database flashback off;
SQL> alter database open;

将数据库设置为归档模式

要使用rman进行联机备份,数据库必须处于归档模式,检查是否是归档模式

1
2
3
sqlplus /nolog
conn / as sysdba
SQL> archive log list;

rman-1

修改为归档模式

1
2
3
4
5
SQL> shutdown immediate;
SQL> startup mount;
SQL> alter database archivelog;
SQL> archive log list;
SQL> alter database open;

rman-2 rman-3

图中的 USE_DB_RECOVERY_FILE_DESC 表示归档日志默认使用oracle闪回区,这是之前安装时选择闪回功能导致的,可以选择修改归档日志默认路径,然后重启数据库:

1
alter system set log_archive_dest_1='location=/data/oracle/product/11.2.0/dbhome_1/dbs/archlog';

rman-5

配置rman备份参数

设置备份的并行级别,通道数

1
2
rman target /
RMAN> configure device type disk parallelism 1;

打开控制文件与服务器参数文件的自动备份

1
configure controlfile autobackup on;

启用备份优化

1
configure backup optimization on;

配置备份保留策略,这个参数看自己的需要设置

1
CONFIGURE RETENTION POLICY TO RECOVERY WINDOW OF 1 DAYS;

设置备份的文件路径和格式

1
CONFIGURE CHANNEL DEVICE TYPE DISK FORMAT   '/data/orabak/%F';

以上参数的意思可以网上查询详细说明,根据自己的需要配置,配完参数之后可以 show all 查看刚刚修改过的参数,然后编写rman备份脚本:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
#. /home/oracle/.bash_profile
#source 11.2.0.4 env
. /home/oracle/11g.env

TARGET_DIR=/data/orabak

export START_TIME=`date +"%Y%m%d-%H:%M:%S"`
export logfile=$TARGET_DIR/logfile_FINTEST_rman.log 
export workdate=`date +"%Y%m%d"`
export begindate=`date +"%Y%m%d-%T"`
export agodate=`date -d "1 days ago" +%Y%m%d`

rman target / <<EOF
run {
crosscheck backup;
backup as compressed backupset database format='$TARGET_DIR/bf_%d_%T_%s_%p.db' filesperset=2;
sql 'alter system archive log current';
backup archivelog all format='$TARGET_DIR/arch_%d_%T_%s_%p.arc' delete all input; 
DELETE ARCHIVELOG ALL COMPLETED BEFORE 'SYSDATE-2';
delete noprompt  obsolete device type disk;
delete noprompt archivelog until time 'sysdate-1';
}

exit
EOF

if [ $? -eq 0 ]; then
        echo $workdate' FINTEST数据库RMAN备份 '$begindate' '`date +"%Y%m%d-%T"`' success!' >> $logfile 
        rm -f /data/orabak/*$agodate*.arc
        rm -f /data/orabak/*$agodate*.db
else
        echo $workdate' FINTEST数据库RMAN备份 '$begindate' '`date +"%Y%m%d-%T"`' failed!'  >> $logfile
fi

这个是每天全备一次的脚本,设定一个crontab任务就能每天定时备份了。

数据库恢复

rman的备份恢复到同实例名称的不同数据库很简单,网上资料也很多,此处不再重复写,此次主要写备份恢复到不同数据库实例名的操作,比如从生产库prod_db恢复到测试库test_db,网上的帖子比较乱,这里写一个可以实际操作的版本。

源数据库db_name和sid都为DMSTEST,新数据库db_name为FIN_TEST,sid为FINTEST

拷贝DMSTEST的数据库备份文件到FINTEST服务器的RMAN备份目录

拷贝所有备份文件到新服务,包括db文件,归档日志文件和控制文件,使用scp或者移动硬盘都可以,略。

修改初始化参数文件,修改数据库实例名

cd $ORACLE_HOME/dbs 找到initFINTEST.ora文件,如果目录下不存在这个文件,则去 /data/oracle/admin/FIN_TEST/pfile 目录下,会有一个init.ora.9112019164630文件,将此文件复制到$ORACLE_HOME/dbs目录,并修改名称为initFINTEST.ora

vi initFINTEST.ora 将db_name修改为DMSTEST

rman-6

连接RMAN,读取控制文件

1
2
3
4
5
6
7
8
9
10
11
12
rman target /
RMAN> shutdown immediate;
RMAN> startup nomount;
# 从备份的控制文件中复制DBID
RMAN> set DBID= 4271865336;
RMAN> restore controlfile from '/data/orabak/c-4271865336-20191014-00';
# 如果执行此命令报数据库名称不对的错误,见文章最后解决方式
RMAN> alter database mount;
# 查看备份的文件
RMAN> list backup;
RMAN> catalog start with '/data/orabak/';
RMAN> list backup;

登录DMSTEST数据库,查询datafile的路径,并将路径替换成FIN_TEST的

1
2
3
4
SELECT 'set newname for datafile ' || file# || ' to ''' || REPLACE(NAME
            ,'/data/oracle/oradata/DMSTEST/'
            ,'/data/oracle/oradata/FIN_TEST/') || ''';'
  FROM v$datafile;

将复制的内容替换如下脚本set newname部分:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
run{
allocate channel d1 device type disk;
allocate channel d2 device type disk;
allocate channel d3 device type disk;
allocate channel d4 device type disk;
set newname for datafile 1 to '/data/oracle/oradata/FIN_TEST/system01.dbf';
set newname for datafile 2 to '/data/oracle/oradata/FIN_TEST/sysaux01.dbf';
set newname for datafile 3 to '/data/oracle/oradata/FIN_TEST/undotbs01.dbf';
set newname for datafile 4 to '/data/oracle/oradata/FIN_TEST/users01.dbf';
set newname for datafile 5 to '/data/oracle/oradata/FIN_TEST/hdm_data01.dbf';
set newname for datafile 6 to '/data/oracle/oradata/FIN_TEST/fp_data.dbf';
set newname for datafile 7 to '/data/oracle/oradata/FIN_TEST/hdm2019_data01.dbf';
set newname for datafile 8 to '/data/oracle/oradata/FIN_TEST/FIN_PUB_DATA01.dbf';
restore database;
switch datafile all;
recover database;
}

在RMAN窗口中执行,如果报错:RMAN-06054: media recovery requesting unknown archived log for thread 1 with sequence 1055 and starting SCN of 6222833174894

rman-7

则是恢复需要的日志记录在控制文件或恢复目录中找不到。解决方法分两种情况:

  • 如果相关的日志存在且可用的话,就将此日志记录添加到控制文件或恢复目录中。
  • 如果相关的日志已经被删除了或不可用了,那么就按照错误的提示scn将数据库恢复到此scn,本案例是6222833174894。也就是说此时数据库只能进行不完全恢复了,在打开数据库时得使用resetlogs打开。

此处只能采用第二种

recover database until scn 6222833174894;

修改logfile路径

在DMSTEST中查询logfile路径,并替换成新的路径

1
2
3
4
SELECT 'alter database rename file ''' || MEMBER || ''' to ''' || REPLACE(MEMBER
            ,'/data/oracle/oradata/DMSTEST/'
            ,'/data/oracle/oradata/FIN_TEST/') || ''';'
  FROM v$logfile;

将结果复制出来到FIN_TEST的sqlplus下dba执行

1
2
3
alter database rename file '/data/oracle/oradata/DMSTEST/redo01.log' to '/data/oracle/oradata/FIN_TEST/redo01.log';
alter database rename file '/data/oracle/oradata/DMSTEST/redo02.log' to '/data/oracle/oradata/FIN_TEST/redo02.log';
alter database rename file '/data/oracle/oradata/DMSTEST/redo03.log' to '/data/oracle/oradata/FIN_TEST/redo03.log';

启动数据库

1
alter database open resetlogs;

生成控制文件的trace文件,并关闭数据库

这个文件可以自定义路径和名称,只是临时输出内容,方便后续复制里面的语句进行更改得到生成控制文件的脚本,使用完成后可以删除该文件。

1
2
3
alter database backup controlfile to trace as '/home/oracle/test.ora';

shutdown immediate;

修改初始化参数,将数据库名称改回FIN_TEST

vi initFINTEST.ora

rman-8

重建控制文件

1
2
3
sqlplus /nolog
SQL> conn /as sysdba
SQL> startup nomount;

打开之前生成的test.ora文件,复制如下内容

rman-9

修改为

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
-- 注意不只是修改路径和名称,CREATE后面的语句也发生了修改
CREATE CONTROLFILE SET DATABASE "FIN_TEST" RESETLOGS NOARCHIVELOG
    MAXLOGFILES 16
    MAXLOGMEMBERS 3
    MAXDATAFILES 100
    MAXINSTANCES 8
    MAXLOGHISTORY 292
LOGFILE
  GROUP 1 '/data/oracle/oradata/FIN_TEST/redo01.log'  SIZE 1024M BLOCKSIZE 512,
  GROUP 2 '/data/oracle/oradata/FIN_TEST/redo02.log'  SIZE 1024M BLOCKSIZE 512,
  GROUP 3 '/data/oracle/oradata/FIN_TEST/redo03.log'  SIZE 1024M BLOCKSIZE 512
-- STANDBY LOGFILE
DATAFILE
  '/data/oracle/oradata/FIN_TEST/system01.dbf',
  '/data/oracle/oradata/FIN_TEST/sysaux01.dbf',
  '/data/oracle/oradata/FIN_TEST/undotbs01.dbf',
  '/data/oracle/oradata/FIN_TEST/users01.dbf',
  '/data/oracle/oradata/FIN_TEST/hdm_data01.dbf',
  '/data/oracle/oradata/FIN_TEST/fp_data.dbf',
  '/data/oracle/oradata/FIN_TEST/hdm2019_data01.dbf',
  '/data/oracle/oradata/FIN_TEST/FIN_PUB_DATA01.dbf'
CHARACTER SET AL32UTF8

在sqlplus中执行上面的脚本,可能会报错

1
2
3
4
5
6
ERROR at line 1:
ORA-01503: CREATE CONTROLFILE failed
ORA-00200: control file could not be created
ORA-00202: control file: '/data/oracle/oradata/FIN_TEST/control01.ctl'
ORA-27038: created file already exists
Additional information: 1 

rman-10

去 /data/oracle/oradata/FIN_TEST/ 目录删除所有control*.ctl文件,然后重新执行脚本,成功后会生成新的控制文件。

rman-11

启动数据库

1
SQL> alter database open resetlogs;

修改临时表空间

去DMSTEST下查询临时表空间,并替换路径

1
2
3
4
select 'ALTER TABLESPACE ' || t.TABLESPACE_NAME || ' ADD TEMPFILE ''' ||
       replace(t.FILE_NAME, '/data/oracle/oradata/DMSTEST/', '/data/oracle/oradata/FIN_TEST/') ||
       ''' size 2000M ;'
  from dba_temp_files t;

复制所有结果到FIN_TEST的sqlplus中执行

1
ALTER TABLESPACE TEMP ADD TEMPFILE '/data/oracle/oradata/FIN_TEST/temp01.dbf' size 2000M ;

如果报错

1
2
ORA-01119: error in creating database file '/data/oracle/oradata/FIN_TEST/temp01.dbf'
ORA-27038: created file already exists

rman-12

则去掉 size 2000M,重新执行修改路径。

1
ALTER TABLESPACE TEMP ADD TEMPFILE '/data/oracle/oradata/FIN_TEST/temp01.dbf';

此时数据恢复已完成,登录FIN_TEST数据库验证数据是否已完全恢复,如果数据没有问题,则需要再手动修改数据库为归档模式运行,因为前面重建控制文件时已经将数据库修改为非归档模式运行了。

以上就是rman恢复数据的全部过程。

解决数据库名称错误

如果在执行 alter database mount; 时报错:database name ‘DMSTEST’ in control file is not ‘FIN_TEST’

rman-13

则需要修改数据库的启动参数文件,首先将数据库参数从 spfile 写到 pfile文件

1
2
-- 数据库必须是以spfile方式启动的,pfile路径和名称可以随意定义
create pfile='/home/oracle/pfile.11' from spfile;

rman-14

打开刚刚生成的 pfile.11 文件,修改 db_name

rman-15

停掉数据库,然后从 pfile 文件创建新的 spfile 文件,再启动 nomount 状态

1
2
3
shutdown immediate;
create spfile from pfile='/home/oracle/pfile.11';
startup nomount;

rman-16

再次执行 alter database mount; 命令

rman-17

此时数据库正常打开,然后可以继续之前的操作。但是在rman恢复后,除了修改 initFINTEST.ora 文件之外,还需要再次执行一遍修改spfile操作,将 db_name 修改回来。