冷备下模拟rm -rf *.dbf恢复案例
关于备份恢复一直是所有关系型数据库的重头戏。下面会介绍冷备数据库,并模拟破坏数据文件进行恢复数据库,并涉及到其他相关内容。
[Oracle@localhost ~]$ cat /etc/RedHat-release
Red Hat Enterprise Linux Server release 5.5 (Tikanga)
SQL> select * from v$version where rownum<2;
BANNER
--------------------------------------------------------------------------------
Oracle Database 11g Enterprise Edition Release 11.2.0.1.0 - Production
首先介绍一下冷备份(完全脱机备份),需要把数据库shutdown后,粘贴复制就可了,先备份先:
SQL> shutdown immediate;
数据库已经关闭。
已经卸载数据库。
ORACLE 例程已经关闭。
[oracle@localhost orcl3939]$ cp *.dbf /home/oracle/beifeng
[oracle@localhost orcl3939]$ cp *.log /home/oracle/beifeng
[oracle@localhost orcl3939]$ cp *.ctl /home/oracle/beifeng
控制文件只需要备份一份就行了,因为是镜像文件,完全一样。
是不是很简单!
这种方式适合archivelog和noarchivelog,其中涉及到了几类文件:
logfile:v$log v$logfile
controlfile:v$controlfile
datafile:dba_data_files
temp files:dba_temp_files
其中的临时文件并不是我们备份的对象,因为备份文件可以理解成数据库的虚拟内存,如linux中,我们分区时,如果内存较小时,可以分配swap分区,作用是交换缓存数据,作为内存不足的一种选择而已。
关于archivelog和noarchivelog,生产环境中几乎都是archivelog:
SQL> archive log list;
数据库日志模式 非存档模式
自动存档 禁用
存档终点 USE_DB_RECOVERY_FILE_DEST
最早的联机日志序列 424
当前日志序列 426
此时我的练习库是非归档模式,那我们启动归档模式:
SQL> startup mount;
ORACLE 例程已经启动。
SQL> alter database archivelog;
数据库已更改。
SQL> select log_mode from v$database;
LOG_MODE
------------
ARCHIVELOG
此时数据库已经是归档模式。
关于归档文件存放位置,看参数:
SQL> show parameter db_recover
NAME TYPE VALUE
------------------------------------ ----------- ------------------------------
db_recovery_file_dest string /u01/app/oracle/flash_recovery
_area
db_recovery_file_dest_size big integer 3852M
第一个参数是存放位置,第二个参数是该空间的大小。
flash_recovery _area目录是10g才有的,便于管理归档等文件。
我们可以修改db_recovery_file_dest:
SQL> alter system set db_recovery_file_dest =' ';
系统已更改。
SQL> show parameter db_recover
NAME TYPE VALUE
------------------------------------ ----------- ------------------------------
db_recovery_file_dest string
db_recovery_file_dest_size big integer 3852M
此时归档文件存放的目录回到了10g之前:
SQL> show parameter log_archive_dest
NAME TYPE VALUE
------------------------------------ ----------- ------------------------------
log_archive_dest string
log_archive_dest_1 string
log_archive_dest_10 string
log_archive_dest_11 string
log_archive_dest_12 string
log_archive_dest_13 string
log_archive_dest_14 string
log_archive_dest_15 string
log_archive_dest_16 string
log_archive_dest_17 string
log_archive_dest_18 string
NAME TYPE VALUE
------------------------------------ ----------- ------------------------------
log_archive_dest_19 string
log_archive_dest_2 string
log_archive_dest_20 string
log_archive_dest_21 string
log_archive_dest_22 string
log_archive_dest_23 string
log_archive_dest_24 string
log_archive_dest_25 string
log_archive_dest_26 string
log_archive_dest_27 string
log_archive_dest_28 string
NAME TYPE VALUE
------------------------------------ ----------- ------------------------------
log_archive_dest_29 string
log_archive_dest_3 string
log_archive_dest_30 string
log_archive_dest_31 string
log_archive_dest_4 string
log_archive_dest_5 string
log_archive_dest_6 string
log_archive_dest_7 string
log_archive_dest_8 string
log_archive_dest_9 string
指定目录位置即可用,但是这样很不利于管理。
简介下SCN:System change number | System Commit Number 但是很多情况下理解成第一种更为准确。
SQL> select current_scn from v$database;
CURRENT_SCN
-----------
0
SQL> alter database open;
数据库已更改。
SQL> select current_scn from v$database;
CURRENT_SCN
-----------
7232872
SQL> select current_scn from v$database;
CURRENT_SCN
-----------
7232878
SQL> select current_scn from v$database;
CURRENT_SCN
-----------
7232879
SQL> select current_scn from v$database;
CURRENT_SCN
-----------
7232905
SQL> select current_scn from v$database;
CURRENT_SCN
-----------
7232915
SQL> select current_scn from v$database;
CURRENT_SCN
-----------
7232917
SCN是oracle的一种时钟机制,随时间而增加,每个数据库都有一个全局SCN,通过SCN oracle来维护数据库的一致性。SCN无处不在,resetlogs scn,checkpoint scn.......
除非数据库重建,否则永远不会为0,上面出现0,是因为数据库还没打开啦。
此时我们在sysY用户下:
SQL> show user;
USER 为 "SYS"
SQL> create table tt(id number,scn number);
表已创建。
SQL> insert into tt values(1,dbms_flashback.get_system_change_number);
已创建 1 行。
SQL> insert into tt values(2,dbms_flashback.get_system_change_number);
已创建 1 行。
SQL> commit;
提交完成。
SQL> select * from tt;
ID SCN
---------- ----------
1 7235265
2 7235294
通过查找tt,可以大致估算我们插入数据时的时间。
查看v$log:
SQL> select group#,status,archived,sequence#,first_change#,next_change# from v$log;
GROUP# STATUS ARC SEQUENCE# FIRST_CHANGE# NEXT_CHANGE#
---------- ---------------- --- ---------- ------------- ------------
1 INACTIVE YES 424 7179754 7189656
2 INACTIVE YES 425 7189656 7227701
3 CURRENT NO 426 7227701 2.8147E+14
有上述插入数据的SCN和目前日志的FIRST_CHANGE#知,上述数据的日志存放在当前日志文件中,也就是序列号为426。上述的FIRST_CHANGE#表示开始使用该组日志时的scn,
next_change#表示切换该组日志时的scn,也就是使用下一组日志的FIRST_CHANGE#。
分析一下status:
current:表示目前使用的日志,毫无疑问。
active:已经完成归档,日志文件已经写入磁盘,可能和该部分日志相对应的数据块的修改还没有写入磁盘,在内存里,所以该日志文件在数据库crash后恢复可能会用到。
inactive:此时已经完成归档,日志文件和对应修改的数据库已经写入磁盘。
由于这三组日志循环切换,产生的日志我们怎么标识呢,
这就是序列号重要的作用了:
SQL> alter system switch logfile;
系统已更改。
SQL> select name,thread#,sequence#,first_change#,next_change# from v$archived_log WHERE sequence# = 426;
NAME THREAD# SEQUENCE# FIRST_CHANGE# NEXT_CHANGE#
--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- ---------- ---------- ------------- ------------
/u01/app/oracle/flash_recovery_area/ORCL3939/archivelog/2015_04_27/o1_mf_1_426_bmvr5f9j_.arc 1 426 7227701 7236412
看上面的 name,sequence#,知道序列用来标识归档文件的作用了吧。
THREAD#:因为此时数据库是在单实例下,一个数据库对应一个实例:
所以此时thread#可以理解为实例编号。
在RAC下,此时的THREAD#对应的是节点号。
我们现在模拟:
SQL> insert into tt values(3,dbms_flashback.get_system_change_number
2 );
已创建 1 行。
SQL> commit;
提交完成。
SQL> alter system switch logfile;
系统已更改。
SQL> insert into tt values(4,dbms_flashback.get_system_change_number
2 );
已创建 1 行。
SQL> COMMIT;
提交完成。
SQL> alter system switch logfile;
系统已更改。
SQL> insert into tt values(5,dbms_flashback.get_system_change_number);
已创建 1 行。
SQL> COMMIT;
提交完成。
SQL> alter system switch logfile;
系统已更改。
SQL> select * from v$log;
GROUP# THREAD# SEQUENCE# BYTES BLOCKSIZE MEMBERS ARC STATUS FIRST_CHANGE# FIRST_TIME NEXT_CHANGE# NEXT_TIME
---------- ---------- ---------- ---------- ---------- ---------- --- ---------------- ------------- -------------- ------------ --------------
1 1 433 52428800 512 1 NO CURRENT 7239074 27-4月 -15 2.8147E+14
2 1 431 52428800 512 1 YES ACTIVE 7239029 27-4月 -15 7239057 27-4月 -15
3 1 432 52428800 512 1 YES ACTIVE 7239057 27-4月 -15 7239074 27-4月 -15
我们此时删除数据文件:
[oracle@localhost ~]$ cd /u01/app/oracle/oradata/orcl3939
[oracle@localhost orcl3939]$ rm -rf *.dbf
然后把之前备份的数据文件移到/u01/app/oracle/oradata/orcl3939,如果全部移动的话,则数据库可以打开了,之前对于表tt的操作数据完全丢失
[oracle@localhost beifeng]$ cp *.dbf /u01/app/oracle/oradata/orcl3939
SQL> startup mount;
ORACLE 例程已经启动。
Total System Global Area 351522816 bytes
Fixed Size 1336484 bytes
Variable Size 297798492 bytes
Database Buffers 46137344 bytes
Redo Buffers 6250496 bytes
数据库装载完毕。
此时打开到mount状态是完全可以的。
SQL> alter database open;
alter database open
*
第 1 行出现错误:
ORA-01113: 文件 1 需要介质恢复
ORA-01110: 数据文件 1: '/u01/app/oracle/oradata/orcl3939/system01.dbf'
此时我们恢复数据库:
SQL> recover database;
ORA-00279: 更改 7233493 (在 04/27/2015 13:51:53 生成) 对于线程 1 是必需的 ORA-00289:
建议:
/u01/app/oracle/flash_recovery_area/ORCL3939/archivelog/2015_04_27/o1_mf_1_426_b
mvr5f9j_.arc
ORA-00280: 更改 7233493 (用于线程 1) 在序列 #426 中
指定日志: {<RET>=suggested | filename | AUTO | CANCEL}
此时会用到归档日志:/u01/app/oracle/flash_recovery_area/ORCL3939/archivelog/2015_04_27/o1_mf_1_426_b
mvr5f9j_.arc
序列号为:426,
更改时的scn:7233493
指定日志分析:
suggest:表示用的归档日志文件位置就是建议的位置
filename:表示归档后的日志若你修改位置,此时你需要指定位置
auto:表示数据库自动恢复
cancle:只恢复到该步骤即停止
下面我们按回车键选择suggest:
ORA-00279: 更改 7236412 (在 04/27/2015 15:09:33 生成) 对于线程 1 是必需的 ORA-00289:
建议:
/u01/app/oracle/flash_recovery_area/ORCL3939/archivelog/2015_04_27/o1_mf_1_427_b
mvrj552_.arc
ORA-00280: 更改 7236412 (用于线程 1) 在序列 #427 中
指定日志: {<RET>=suggested | filename | AUTO | CANCEL}
ORA-00279: 更改 7236929 (在 04/27/2015 15:15:17 生成) 对于线程 1 是必需的 ORA-00289:
建议:
/u01/app/oracle/flash_recovery_area/ORCL3939/archivelog/2015_04_27/o1_mf_1_428_b
mvrooz2_.arc
ORA-00280: 更改 7236929 (用于线程 1) 在序列 #428 中
指定日志: {<RET>=suggested | filename | AUTO | CANCEL}
ORA-00279: 更改 7237015 (在 04/27/2015 15:18:13 生成) 对于线程 1 是必需的 ORA-00289:
建议:
/u01/app/oracle/flash_recovery_area/ORCL3939/archivelog/2015_04_27/o1_mf_1_429_b
mvs29ny_.arc
ORA-00280: 更改 7237015 (用于线程 1) 在序列 #429 中
指定日志: {<RET>=suggested | filename | AUTO | CANCEL}
是不是这样很慢,我这样是让大家看到每一步用到的归档日志文件,那下面我们使用auto:
AUTO
ORA-00279: 更改 7237261 (在 04/27/2015 15:24:57 生成) 对于线程 1 是必需的 ORA-00289:
建议:
/u01/app/oracle/flash_recovery_area/ORCL3939/archivelog/2015_04_27/o1_mf_1_430_b
mvvf00h_.arc
ORA-00280: 更改 7237261 (用于线程 1) 在序列 #430 中
已应用的日志。
完成介质恢复。
此时我们查找数据文件的scn(全部来自控制文件,shutdown之后保留的),以及数据头的scn(数据头的scn是旧的,来自拷贝回来的数据文件头)
要想数据库打开,则两者scn相等:
SQL> select file#,checkpoint_change# from v$datafile;
FILE# CHECKPOINT_CHANGE#
---------- ------------------
1 7259884
2 7259884
3 7259884
4 7259884
5 7259884
6 7259884
7 7259884
8 7259884
9 7259884
10 6980281
11 7259884
FILE# CHECKPOINT_CHANGE#
---------- ------------------
12 7259884
已选择12行。
SQL> select file#,checkpoint_change# from v$datafile_header;
FILE# CHECKPOINT_CHANGE#
---------- ------------------
1 7259884
2 7259884
3 7259884
4 7259884
5 7259884
6 7259884
7 7259884
8 7259884
9 7259884
10 6980281
11 7259884
FILE# CHECKPOINT_CHANGE#
---------- ------------------
12 7259884
已选择12行。
现在两者已经对应相等了,此时可以打开数据库。
SQL> alter database open;
数据库已更改。
SQL> select * from tt;
ID SCN
---------- ----------
1 7235265
2 7235294
3 7239015
4 7239050
5 7239064
数据已经全部恢复回来。