冷备下模拟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

数据已经全部恢复回来。

相关推荐