Oracle恢复数据库时有几个常用但非常相似的命令:
- recover database
- recover database until cancel
- recover database until cancel using backup controlfile
- recover database using backup controlfile
- recover database using backup controlfile until cancel
它们区别、作用和适用场景如下:
命令 | 控制文件旧于数据文件 | 完全恢复 | rman/sqlplus执行 | 备注 |
recover database | 不可以 | 是 | rman和sqlplus命令行都可以 | If the CURRENT CONTROLFILE is in use, and all online redo logs are available, then you can simply run RECOVER DATABASE. This will apply all archivelogs, and the current online redolog. |
recover database until cancel | 不可以 | 否 | 只能在sqlplus命令行进行 | 常用于current/active redo丢失时,在归档和联机日志都完整的情况下,你可以通过不完全恢复的语句来实现数据的完全恢复。可以一步一步的跳也就是一个一个归档的应用,也可以AUTO全部应用,当然也可以在恢复完某个archivelog后cancel退出,但是他不会恢复 current logfile,如果需要恢复current logfile需要自己指定。 |
recover database until cancel using backup controlfile | 可以 | 否 | 只能在sqlplus命令行进行 | 与recover database until cancel类似,不同的是它丢失当前的控制文件,需用备份的旧控制文件来恢复。 |
recover database using backup controlfile | 可以 | 否 | 只能在sqlplus命令行进行 | 在归档和联机日志都完整的情况下,你可以通过不完全恢复的语句来实现数据的完全恢复。 |
recover database using backup controlfile until cancel | 可以 | 否 | 只能在sqlplus命令行进行 | 相当于执行recover database using backup controlfile,然后选择AUTO应用所有归档,但不输入redo文件进行应用, |
- recover 带任何using 语句的都是在SQLPLUS中执行,不是在rman中执行。
- 如果控制文件丢失,restore备份的控制文件后,则必须使用using backup controlfile选项。
- until cancel则是不完全恢复,即current/active redo丢失,或者从restore数据库后某个归档文件缺失,则终止;最后打开需用alter database open resetlogs。
下面对一些场景进行测试:
1、准备测试数据
--生成拷贝命令
set pagesize 500
set linesize 500
select 'cp '||''||member||''||' /media/orabackup/ ' from v$logfile
union
select 'cp '||''||name||''||' /media/orabackup/ ' from v$datafile
union
select 'cp '||''||name||''||' /media/orabackup/ ' from v$controlfile
union
select 'cp '||''||name||''||' /media/orabackup/ ' from v$tempfile ;
--测试之前关机,先做一次冷备
SQL> shutdown immediate;
Database closed.
Database dismounted.
ORACLE instance shut down.
执行:
cp /u01/app/oracle/fast_recovery_area/dbbbed/control02.ctl /media/orabackup/
cp /u01/oradata/dbbbed/control01.ctl /media/orabackup/
cp /u01/oradata/dbbbed/mssm01.dbf /media/orabackup/
cp /u01/oradata/dbbbed/redo01.log /media/orabackup/
cp /u01/oradata/dbbbed/redo02.log /media/orabackup/
cp /u01/oradata/dbbbed/redo03.log /media/orabackup/
cp /u01/oradata/dbbbed/sysaux01.dbf /media/orabackup/
cp /u01/oradata/dbbbed/system01.dbf /media/orabackup/
cp /u01/oradata/dbbbed/szr01.dbf /media/orabackup/
cp /u01/oradata/dbbbed/tbst01.dbf /media/orabackup/
cp /u01/oradata/dbbbed/temp01.dbf /media/orabackup/
cp /u01/oradata/dbbbed/test0529.dbf /media/orabackup/
cp /u01/oradata/dbbbed/undotbs01.dbf /media/orabackup/
cp /u01/oradata/dbbbed/users01.dbf /media/orabackup/
--冷备后,打开数据库,插入测试数据
SQL> startup;
ORACLE instance started.
Total System Global Area 3691200512 bytes
Fixed Size 2258680 bytes
Variable Size 788531464 bytes
Database Buffers 2885681152 bytes
Redo Buffers 14729216 bytes
SQL> archive log list;
Database log mode Archive Mode
Automatic archival Enabled
Archive destination /u01/arch/
Oldest online log sequence 52
Next log sequence to archive 54
Current log sequence 54
conn szr/szr
create table fruits(name varchar2(10));
insert into fruits values('apple');
insert into fruits values('banana');
insert into fruits values('orange');
commit;
alter system switch logfile; <<<<< 归档到54号,1_54_1170455884.dbf
SQL> select sysdate from dual;
SYSDATE
-------------------
2024-07-29 15:53:25
--归档日志文件中已经有我们的数据了
$ strings 1_54_1170455884.dbf|grep orange
orange
--关闭数据库再做下冷备(第二次冷备),备份联机重做日志文件、控制文件和数据文件
SQL> shutdown immediate;
Database closed.
Database dismounted.
ORACLE instance shut down.
执行:
mkdir /media/orabackup2/
cp /u01/app/oracle/fast_recovery_area/dbbbed/control02.ctl /media/orabackup2/
cp /u01/oradata/dbbbed/control01.ctl /media/orabackup2/
cp /u01/oradata/dbbbed/mssm01.dbf /media/orabackup2/
cp /u01/oradata/dbbbed/redo01.log /media/orabackup2/
cp /u01/oradata/dbbbed/redo02.log /media/orabackup2/
cp /u01/oradata/dbbbed/redo03.log /media/orabackup2/
cp /u01/oradata/dbbbed/sysaux01.dbf /media/orabackup2/
cp /u01/oradata/dbbbed/system01.dbf /media/orabackup2/
cp /u01/oradata/dbbbed/szr01.dbf /media/orabackup2/
cp /u01/oradata/dbbbed/tbst01.dbf /media/orabackup2/
cp /u01/oradata/dbbbed/temp01.dbf /media/orabackup2/
cp /u01/oradata/dbbbed/test0529.dbf /media/orabackup2/
cp /u01/oradata/dbbbed/undotbs01.dbf /media/orabackup2/
cp /u01/oradata/dbbbed/users01.dbf /media/orabackup2/
--重新打开数据库,往表里继续插入数据
SQL> startup;
ORACLE instance started.
Total System Global Area 3691200512 bytes
Fixed Size 2258680 bytes
Variable Size 788531464 bytes
Database Buffers 2885681152 bytes
Redo Buffers 14729216 bytes
Database mounted.
Database opened.
conn szr/szr
insert into fruits values ('grape');
commit;
SQL>alter system switch logfile; <<<<< 归档到55号,1_55_1170455884.dbf
System altered.
SQL> select sysdate from dual;
SYSDATE
-------------------
2024-07-29 16:10:38
--归档日志文件中已经有我们的数据了
$ strings 1_55_1170455884.dbf |grep grape
grape
--在插入一条数据,不做归档,只存在redo日志里
insert into fruits values ('peach');
commit;
SQL> select group#,sequence#,status,archived from v$log;
GROUP# SEQUENCE# STATUS ARC
---------- ---------- ---------------- ---
1 55 INACTIVE YES
2 56 CURRENT NO <<<当前redo
3 54 INACTIVE YES
--fruits.name='peach'这条数据在数据文件和联机重做日志文件里面都有,没有在归档日志里面
$ strings redo02.log |grep peach
peach
--关闭数据库,做第三次冷备
SQL> shutdow immediate;
Database closed.
Database dismounted.
ORACLE instance shut down
执行:
mkdir /media/orabackup3/
cp /u01/app/oracle/fast_recovery_area/dbbbed/control02.ctl /media/orabackup3/
cp /u01/oradata/dbbbed/control01.ctl /media/orabackup3/
cp /u01/oradata/dbbbed/mssm01.dbf /media/orabackup3/
cp /u01/oradata/dbbbed/redo01.log /media/orabackup3/
cp /u01/oradata/dbbbed/redo02.log /media/orabackup3/
cp /u01/oradata/dbbbed/redo03.log /media/orabackup3/
cp /u01/oradata/dbbbed/sysaux01.dbf /media/orabackup3/
cp /u01/oradata/dbbbed/system01.dbf /media/orabackup3/
cp /u01/oradata/dbbbed/szr01.dbf /media/orabackup3/
cp /u01/oradata/dbbbed/tbst01.dbf /media/orabackup3/
cp /u01/oradata/dbbbed/temp01.dbf /media/orabackup3/
cp /u01/oradata/dbbbed/test0529.dbf /media/orabackup3/
cp /u01/oradata/dbbbed/undotbs01.dbf /media/orabackup3/
cp /u01/oradata/dbbbed/users01.dbf /media/orabackup3/
2、recover database场景测试
在普通的recover database或者recover tablespace,recover datafile时,Oracle会以当前controlfile记录的SCN为准,利用archive log和redo log,把相关datafile的block恢复到“当前controlfile记录的SCN”。
使用场景:既然恢复是以控制文件中的SCN为目标,当然要求控制文件不能比数据文件旧(控制文件SCN>=数据文件SCN)。
所以使用场景要么是控制文件完好,数据文件是从备份中恢复的,要么控制文件和数据文件都是从备份中恢复的。
--把第一次冷备的数据文件还原回去(只还原数据文件,其他的不还原)
SQL> shutdown immediate;
Database closed.
Database dismounted.
ORACLE instance shut down
$ cd /media/orabackup
$ cp *.dbf /u01/oradata/dbbbed/
--启动到mount状态
SQL> startup mount;
ORACLE instance started.
Total System Global Area 3691200512 bytes
Fixed Size 2258680 bytes
Variable Size 788531464 bytes
Database Buffers 2885681152 bytes
Redo Buffers 14729216 bytes
Database mounted.
--执行recover database
SQL> recover database;
Media recovery complete.
--打开数据库
SQL> alter database open;
Database altered.
SQL> select * from szr.fruits;
NAME
------------------------------------------------------------
apple
banana
orange
grape
peach
进行recover database,数据完全恢复,无丢失。
3、recover database until cancel 场景测试
也要求控制文件不能比数据文件旧,在丢失current/active redo时手动指定恢复终点,用于不完全恢复。这个命令只能在SQL命令行进行,通过提示归档日志文件的建议名称进行主动恢复,应用到哪个归档由你自己把控。
在归档和联机日志都完整的情况下,你甚至可以通过不完全恢复的语句来实现数据的完全恢复。
recover database until cancel 命令输入AUTO选项时只会应用归档日志,而不会自动应用redo日志,这是和recover database的区别,后者自动应用所有归档和在线日志进行前滚操作。
--把第一次冷备的数据文件还原回去(只还原数据文件,其他的不还原)
SQL> shutdown immediate;
Database closed.
Database dismounted.
ORACLE instance shut down
$ cd /media/orabackup
$ cp *.dbf /u01/oradata/dbbbed/
--删除redo 日志,模拟日志丢失
rm -rf redo01.log redo02.log redo03.log
--启动到mount状态
SQL> startup mount;
--执行recover database until cancel恢复
SQL> recover database until cancel;
ORA-00279: change 4954281 generated at 07/29/2024 15:47:29 needed for thread 1
ORA-00289: suggestion : /u01/arch/1_54_1170455884.dbf <-- Oracle建议应用的日志
ORA-00280: change 4954281 for thread 1 is in sequence #54
Specify log: {<RET>=suggested | filename | AUTO | CANCEL}
auto
ORA-00279: change 4954668 generated at 07/29/2024 15:53:41 needed for thread 1
ORA-00289: suggestion : /u01/arch/1_55_1170455884.dbf <-- Oracle建议下一个应用的日志
ORA-00280: change 4954668 for thread 1 is in sequence #55
ORA-00278: log file '/u01/arch/1_54_1170455884.dbf' no longer needed for this recovery <-- 1_54_1170455884.dbf已应用完,不再需要
ORA-00279: change 4955570 generated at 07/29/2024 16:10:33 needed for thread 1
ORA-00289: suggestion : /u01/arch/1_56_1170455884.dbf
ORA-00280: change 4955570 for thread 1 is in sequence #56
ORA-00278: log file '/u01/arch/1_55_1170455884.dbf' no longer needed for this recovery
ORA-00308: cannot open archived log '/u01/arch/1_56_1170455884.dbf'
ORA-27037: unable to obtain file status
Linux-x86_64 Error: 2: No such file or directory
Additional information: 3
输入auto,让Oracle自动应用归档日志文件,由于只归档到55,56这个是在redo日志,所以提示找不到56这个归档日志。
--open resetlogs打开数据库
SQL> alter database open resetlogs;
Database altered.
SQL> select * from szr.fruits;
NAME
------------------------------------------------------------
apple
banana
orange
grape
<<< 可以看到丢失了一条数据,peach 那条数据是在redo日志。如果redo日志存在情况,recover database until cancel执行恢复时,可以手动指定redo日志,相当于完全恢复,数据可以不丢。
4、recover database using backup controlfile 和 recover database using backup controlfile until cancel 场景测试
recover database using backup controlfile:
如果数据文件完好,而全部控制文件丢失,需要从备份中还原,此时控制文件就比数据文件旧(控制文件SCN<数据文件SCN),只使用recover database恢复到还原出来的控制文件SCN是打不开数据库的。这时就需要用到recover database using backup controlfile告诉oracle,不要以还原出来的控制文件作为恢复的终点,而要恢复到比它更靠后的位置,
恢复时可以看到提示 Specify log: {=suggested | filename | AUTO | CANCEL}。通常选择AUTO应用所有归档,但注意AUTO不会应用redo日志,需要手动输入redo文件进行应用。
然后通过alter database open resetlogs命令打开
recover database using backup controlfile until cancel:
如果数据文件完好,全部控制文件丢失,并且current/active redo都丢失。
执行这个命令相当于执行recover database using backup controlfile,然后选择AUTO应用所有归档,但不输入redo文件进行应用(因为已经丢了),明显这也是一种不完全恢复,current/active redo中的数据会丢失。
----模拟控制文件丢失情况
SQL> shutdown immediate;
Database closed.
Database dismounted.
ORACLE instance shut down.
SQL>
--恢复第三次冷备的数据文件和redo log
$ cd /media/orabackup3
$ cp *.dbf /u01/oradata/dbbbed/
$ cp redo* /u01/oradata/dbbbed/
--恢复第二次冷备的控制文件
$ cd /media/orabackup2/
$ cp control01.ctl /u01/oradata/dbbbed/
$ cp control02.ctl /u01/app/oracle/fast_recovery_area/dbbbed/
--启动到mount状态
SQL> startup mount;
ORACLE instance started.
Total System Global Area 3691200512 bytes
Fixed Size 2258680 bytes
Variable Size 788531464 bytes
Database Buffers 2885681152 bytes
Redo Buffers 14729216 bytes
SQL> select name,checkpoint_change# from v$datafile;
NAME CHECKPOINT_CHANGE#
-------------------------------------------------- ------------------
/u01/oradata/dbbbed/system01.dbf 4955039
/u01/oradata/dbbbed/sysaux01.dbf 4955039
/u01/oradata/dbbbed/undotbs01.dbf 4955039
/u01/oradata/dbbbed/users01.dbf 4955039
/u01/oradata/dbbbed/tbst01.dbf 4955039
/u01/oradata/dbbbed/szr01.dbf 4955039
/u01/oradata/dbbbed/mssm01.dbf 4955039
/u01/oradata/dbbbed/test0529.dbf 4955039
8 rows selected.
SQL> select name,checkpoint_change# from v$datafile_header;
NAME CHECKPOINT_CHANGE#
-------------------------------------------------- ------------------
/u01/oradata/dbbbed/system01.dbf 4955994
/u01/oradata/dbbbed/sysaux01.dbf 4955994
/u01/oradata/dbbbed/undotbs01.dbf 4955994
/u01/oradata/dbbbed/users01.dbf 4955994
/u01/oradata/dbbbed/tbst01.dbf 4955994
/u01/oradata/dbbbed/szr01.dbf 4955994
/u01/oradata/dbbbed/mssm01.dbf 4955994
/u01/oradata/dbbbed/test0529.dbf 4955994
8 rows selected.
上面可以看到数据文件头中记录的SCN比控制文件中记录的SCN要大,此时用recover database会报错:
SQL> recover database;
ORA-00283: recovery session canceled due to errors
ORA-01122: database file 1 failed verification check
ORA-01110: data file 1: '/u01/oradata/dbbbed/system01.dbf'
ORA-01207: file is more recent than control file - old control file
因为数据文件比控制文件要新,recover database(不加using backup controlfile)命令是把数据库恢复到控制文件记录的最大SCN,不可能使用recover命令来把数据库恢复到过去的一个时间点,
闪回数据库需要用flashback database(使用闪回日志),如果使用using backup controlfile,则是告诉Oracle把数据库恢复到数据文件头记录的最大SCN,同时也会把控制文件恢复到最新,下面来实验下:
SQL> recover database using backup controlfile;
ORA-00279: change 4955039 generated at 07/29/2024 15:53:41 needed for thread 1
ORA-00289: suggestion : /u01/arch/1_55_1170455884.dbf
ORA-00280: change 4955039 for thread 1 is in sequence #55
Specify log: {<RET>=suggested | filename | AUTO | CANCEL}
auto <<<<<<这时候我输入auto让Oracle自动应用归档日志文件
ORA-00279: change 4955570 generated at 07/29/2024 16:10:33 needed for thread 1
ORA-00289: suggestion : /u01/arch/1_56_1170455884.dbf
ORA-00280: change 4955570 for thread 1 is in sequence #56
ORA-00278: log file '/u01/arch/1_55_1170455884.dbf' no longer needed for this recovery
ORA-00308: cannot open archived log '/u01/arch/1_56_1170455884.dbf' <<<<<找不到56这个归档,这个在redo日志里,还没切换出来。
ORA-27037: unable to obtain file status
Linux-x86_64 Error: 2: No such file or directory
Additional information: 3
发现没有,使用using backup controlfile时,当Oracle找不到可以应用的归档日志文件时,它就自动结束这个命令了。
因为using backup controlfile是不完全恢复,不会去应用联机重组日志,当找不到所需的归档日志时,就报错了,下面我们加上until cancel试试
SQL> recover database using backup controlfile until cancel;
ORA-00279: change 4955570 generated at 07/29/2024 16:10:33 needed for thread 1
ORA-00289: suggestion : /u01/arch/1_56_1170455884.dbf
ORA-00280: change 4955570 for thread 1 is in sequence #56
Specify log: {<RET>=suggested | filename | AUTO | CANCEL}
虽然Oracle找不到这个归档/u01/arch/1_56_1170455884.dbf,但是它会进行提示,你可以输入filename,auto,或cancel,
我们插入的最后一条数据name='peach'在联机重做日志文件redo02.log里面,不在归档日志里面,这时我们输入联机重做日志文件的路径和名称
SQL> recover database using backup controlfile until cancel;
ORA-00279: change 4955570 generated at 07/29/2024 16:10:33 needed for thread 1
ORA-00289: suggestion : /u01/arch/1_56_1170455884.dbf
ORA-00280: change 4955570 for thread 1 is in sequence #56
Specify log: {<RET>=suggested | filename | AUTO | CANCEL}
/u01/oradata/dbbbed/redo02.log <<<<<<<<输入联机重做日志文件的路径和名称
Log applied.
Media recovery complete.
已经成功恢复了,可以说是完全恢复,但是由于我们使用备份的控制文件(using backup controlfile),我们还是需要用resetlogs打开数据库
SQL> alter database open;
alter database open
*
ERROR at line 1:
ORA-01589: must use RESETLOGS or NORESETLOGS option for database open
SQL> alter database open resetlogs;
Database altered.
SQL> select * from szr.fruits;
NAME
--------------------------------------------------
apple
banana
orange
grape
peach --已经完全恢复
关注我,学习更多的数据库知识