揭密备份恢复的原理!

揭密备份恢复的原理!

其实一句话就可以说明白:那就是数据文件的头上不仅包含了checkpoint_change#,更重要的是它包含了这个 checkpoint_change#所在的logfile的sequence#,准确的说是rba。有了rba,在恢复时就能准确的知道到底需要哪个 logfile(archivelog or redo)。
结果花了很大篇幅,只想以试验的方式做个简单的验证,便于大家理解。欢迎拍砖!
另外提个问题:是否存在一些数据字典它是源于redo的?

--controlfile中记录的checkpoint_change#
SQL> select checkpoint_change# from v$database;

CHECKPOINT_CHANGE#
------------------
           1951985
--datafile中记录的checkpoint_change#
SQL> select checkpoint_change#,checkpoint_time from v$datafile_header;

CHECKPOINT_CHANGE# CHECKPOINT_TIME
------------------ -------------------
           1951985 2008/10/01 14:17:00
           1951985 2008/10/01 14:17:00
           1951985 2008/10/01 14:17:00
           1951985 2008/10/01 14:17:00
--controlfile中记录的每一个datafile的checkpoint_change#
SQL> select checkpoint_change#,checkpoint_time from v$datafile;

CHECKPOINT_CHANGE# CHECKPOINT_TIME
------------------ -------------------
           1951985 2008/10/01 14:17:00
           1951985 2008/10/01 14:17:00
           1951985 2008/10/01 14:17:00
           1951985 2008/10/01 14:17:00
--controlfile中记录的redo的checkpoint_change#
SQL> select checkpoint_change#,checkpoint_time from v$thread;

CHECKPOINT_CHANGE# CHECKPOINT_TIME
------------------ -------------------
           1951985 2008/10/01 14:17:00

SQL> alter system checkpoint;

系统已更改。
--检查点发生之后,上面提到的checkpoint_change#都给更新
SQL> select checkpoint_change# from v$database;

CHECKPOINT_CHANGE#
------------------
           1955601

SQL> select checkpoint_change#,checkpoint_time from v$datafile_header;

CHECKPOINT_CHANGE# CHECKPOINT_TIME
------------------ -------------------
           1955601 2008/10/01 16:15:26
           1955601 2008/10/01 16:15:26
           1955601 2008/10/01 16:15:26
           1955601 2008/10/01 16:15:26

SQL> select checkpoint_change#,checkpoint_time from v$datafile;

CHECKPOINT_CHANGE# CHECKPOINT_TIME
------------------ -------------------
           1955601 2008/10/01 16:15:26
           1955601 2008/10/01 16:15:26
           1955601 2008/10/01 16:15:26
           1955601 2008/10/01 16:15:26

SQL> select checkpoint_change#,checkpoint_time from v$thread;

CHECKPOINT_CHANGE# CHECKPOINT_TIME
------------------ -------------------
           1955601 2008/10/01 16:15:26

SQL> shutdown immediate
数据库已经关闭。
已经卸载数据库。
ORACLE 例程已经关闭。
--冷备份db,为下面的恢复试验使用
SQL> startup mount
ORACLE 例程已经启动。

Total System Global Area  163577856 bytes
Fixed Size                  1247876 bytes
Variable Size              92276092 bytes
Database Buffers           67108864 bytes
Redo Buffers                2945024 bytes
数据库装载完毕。
--查看备份时刻的checkpoint_change#,此时的checkpoint_change#=1955692
是实例shutdown时系统所做的完全检查点对应的checkpoint_change#,下面
在恢复时还会看到这个checkpoint_change#:1955692
SQL> select checkpoint_change# from v$database;

CHECKPOINT_CHANGE#
------------------
           1955692

SQL> select checkpoint_change#,checkpoint_time from v$datafile_header;

CHECKPOINT_CHANGE# CHECKPOINT_TIME
------------------ -------------------
           1955692 2008/10/01 16:17:24
           1955692 2008/10/01 16:17:24
           1955692 2008/10/01 16:17:24
           1955692 2008/10/01 16:17:24

SQL> select checkpoint_change#,checkpoint_time from v$datafile;

CHECKPOINT_CHANGE# CHECKPOINT_TIME
------------------ -------------------
           1955692 2008/10/01 16:17:24
           1955692 2008/10/01 16:17:24
           1955692 2008/10/01 16:17:24
           1955692 2008/10/01 16:17:24

SQL> select checkpoint_change#,checkpoint_time from v$thread;

CHECKPOINT_CHANGE# CHECKPOINT_TIME
------------------ -------------------
           1955692 2008/10/01 16:17:24

SQL> alter database open;

数据库已更改。
--输入测试数据,验证备份恢复的过程,注意仔细观查插入到tt表中的dbms_flashback.get_system_change_number
和v$log中的FIRST_CHANGE#之间的关系,我们通常理解备份恢复的原理是:事务对应的scn如果落在了哪个archivelog
里,那么这个archivelog在恢复时就被用到,下面的大致试验过程也会验证这一点:
SQL> connect test/test
已连接。
SQL> select group#,status,sequence#,archived,first_change# from v$log;

    GROUP# STATUS            SEQUENCE# ARC FIRST_CHANGE#
---------- ---------------- ---------- --- -------------
         1 INACTIVE                 74 YES       1926639
         2 CURRENT                  76 NO        1951985
         3 INACTIVE                 75 YES       1947901

SQL> truncate table tt;

表被截断。

SQL> desc tt
名称                                      是否为空? 类型
----------------------------------------- -------- ----------------------------

ID                                                 NUMBER(38)
NAME                                               VARCHAR2(10)

SQL> insert into tt values(dbms_flashback.get_system_change_number,'a');

已创建 1 行。

SQL> commit;

提交完成。

SQL> connect / as sysdba
已连接。
--datafile header上记录的rba信息,rba的意义在下面做了详细解释,这里只需
知道FHRBA_SEQ表示redo的sequence#=76对应的是当前联机日志,而该sequence#被
记录在了datafile header上
SQL> select hxfil,fhrba_seq,fhrba_bno,fhrba_bof from  x$kcvfh;

     HXFIL  FHRBA_SEQ  FHRBA_BNO  FHRBA_BOF
---------- ---------- ---------- ----------
         1         76       6618         16
         2         76       6618         16
         3         76       6618         16
         4         76       6618         16

SQL> select group#,status,sequence#,archived,first_change# from v$log;

    GROUP# STATUS            SEQUENCE# ARC FIRST_CHANGE#
---------- ---------------- ---------- --- -------------
         1 INACTIVE                 74 YES       1926639
         2 CURRENT                  76 NO        1951985
         3 INACTIVE                 75 YES       1947901
SQL> insert into test.tt values(dbms_flashback.get_system_change_number,'b');

已创建 1 行。

SQL> commit;

提交完成。

SQL> alter system switch logfile;

系统已更改。

SQL> select group#,status,sequence#,archived,first_change# from v$log;

    GROUP# STATUS            SEQUENCE# ARC FIRST_CHANGE#
---------- ---------------- ---------- --- -------------
         1 CURRENT                  77 NO        1956233
         2 ACTIVE                   76 YES       1951985
         3 INACTIVE                 75 YES       1947901

SQL> select hxfil,fhrba_seq,fhrba_bno,fhrba_bof from  x$kcvfh;

     HXFIL  FHRBA_SEQ  FHRBA_BNO  FHRBA_BOF
---------- ---------- ---------- ----------
         1         76       6618         16
         2         76       6618         16
         3         76       6618         16
         4         76       6618         16

SQL> alter system checkpoint;

系统已更改。

SQL> select hxfil,fhrba_seq,fhrba_bno,fhrba_bof from  x$kcvfh;

     HXFIL  FHRBA_SEQ  FHRBA_BNO  FHRBA_BOF
---------- ---------- ---------- ----------
         1         77          9         16
         2         77          9         16
         3         77          9         16
         4         77          9         16

SQL> select * from test.tt;

        ID NAME
---------- ----------
   1956113 a
   1956225 b

SQL> select group#,status,sequence#,archived,first_change# from v$log;

    GROUP# STATUS            SEQUENCE# ARC FIRST_CHANGE#
---------- ---------------- ---------- --- -------------
         1 CURRENT                  77 NO        1956233
         2 INACTIVE                 76 YES       1951985
         3 INACTIVE                 75 YES       1947901

SQL> insert into test.tt values(dbms_flashback.get_system_change_number,'c');

已创建 1 行。

SQL> commit;

提交完成。

SQL> select group#,status,sequence#,archived,first_change# from v$log;

    GROUP# STATUS            SEQUENCE# ARC FIRST_CHANGE#
---------- ---------------- ---------- --- -------------
         1 CURRENT                  77 NO        1956233
         2 INACTIVE                 76 YES       1951985
         3 INACTIVE                 75 YES       1947901

SQL> alter system switch logfile;

系统已更改。

SQL> select * from test.tt;

        ID NAME
---------- ----------
   1956113 a
   1956225 b
   1956317 c

SQL> select group#,status,sequence#,archived,first_change# from v$log;

    GROUP# STATUS            SEQUENCE# ARC FIRST_CHANGE#
---------- ---------------- ---------- --- -------------
         1 ACTIVE                   77 YES       1956233
         2 INACTIVE                 76 YES       1951985
         3 CURRENT                  78 NO        1956324
SQL> insert into test.tt values(dbms_flashback.get_system_change_number,'d');

已创建 1 行。

SQL> commit;

提交完成。

SQL> alter system switch logfile;

系统已更改。

SQL> select * from test.tt;

        ID NAME
---------- ----------
   1956113 a
   1956225 b
   1956317 c
   1956472 d
--总共往tt表里插入了4条数据,对应的id值(通过dbms_flashback.get_system_change_number获得的)
都大于sequence#=76所对应的first_change#:1951985,因此在恢复db时
sequence#=76的归档日志会被用到,还会用到那些归档日志呢?
要看tt表中对应的id值落在了那些归档日志的FIRST_CHANGE#和NEXT_CHANGE#之内,
如果落在其中,则恢复时这个归档日志就会被用到,就这个例子而言,76,77,78号归档日志
在恢复db时都会被用到,接下来的恢复过程也会验证这一点
SQL> select sequence#,first_change#,next_change#  from v$archived_log
  2  where sequence# in (76,77,78) and resetlogs_id=666280390;

SEQUENCE# FIRST_CHANGE# NEXT_CHANGE#
---------- ------------- ------------
        76       1951985      1956233
        77       1956233      1956324
        78       1956324      1956480
--通过dump datafile header中的信息发现datafile header上不仅记录了checkpoint_change#,
更重要的是记录了checkpoint_change#所在的redo sequence#:
SQL> alter session set events 'immediate trace name FILE_HDRS level 12';

会话已更改。
trace file中最有用的信息莫过于:
Checkpointed at scn:  0x0000.001dd9e4 10/01/2008 16:30:40 --checkpoint_change#
thread:1 rba:(0x4e.2.10) --sequence# (rba的含义在下面会有详细介绍)
SQL> select hxfil,fhrba_seq,fhrba_bno,fhrba_bof from  x$kcvfh;

     HXFIL  FHRBA_SEQ  FHRBA_BNO  FHRBA_BOF
---------- ---------- ---------- ----------
         1         79          2         16
         2         79          2         16
         3         79          2         16
         4         79          2         16

SQL> shutdown immediate
数据库已经关闭。
已经卸载数据库。
ORACLE 例程已经关闭。
--拷贝备份的datafile回来
SQL> startup
ORACLE 例程已经启动。

Total System Global Area  163577856 bytes
Fixed Size                  1247876 bytes
Variable Size              92276092 bytes
Database Buffers           67108864 bytes
Redo Buffers                2945024 bytes
数据库装载完毕。
ORA-01113: 文件 1 需要介质恢复
ORA-01110: 数据文件 1: 'E:\ORACLE\PRODUCT\10.2.0\ORADATA\TEST\SYSTEM01.DBF'

--为什么会发出"文件 1 需要介质恢复"这样的提示,是因为controlfile
中记录的checkpoint_change#是:1967625,而datafile header上记录的
checkpoint_change#是:1955692
SQL> select checkpoint_change# from v$database;

CHECKPOINT_CHANGE#
------------------
           1967625

SQL> select checkpoint_change# ,checkpoint_time from v$datafile_header;

CHECKPOINT_CHANGE# CHECKPOINT_TIME
------------------ -------------------
           1955692 2008/10/01 16:17:24
           1955692 2008/10/01 16:17:24
           1955692 2008/10/01 16:17:24
           1955692 2008/10/01 16:17:24

SQL> select checkpoint_change# ,checkpoint_time from v$datafile;

CHECKPOINT_CHANGE# CHECKPOINT_TIME
------------------ -------------------
           1967625 2008/10/01 19:06:21
           1967625 2008/10/01 19:06:21
           1967625 2008/10/01 19:06:21
           1967625 2008/10/01 19:06:21

SQL> select checkpoint_change# ,checkpoint_time from v$thread;

CHECKPOINT_CHANGE# CHECKPOINT_TIME
------------------ -------------------
           1967625 2008/10/01 19:06:21
--下面通过dump datafile header中的信息来观查checkpoint_change#和rba的信息,来看看
oracle到底在恢复时是如何使用归档日志的。
SQL> alter session set events 'immediate trace name FILE_HDRS level 12';

会话已更改。
trace file中每个datafile都有一段对应的描述,内容摘录如下:
DATA FILE #1:
  (name #7) E:\ORACLE\PRODUCT\10.2.0\ORADATA\TEST\SYSTEM01.DBF
...............................中间无关内容省略
--==================================
Checkpointed at scn:  0x0000.001dd76c 10/01/2008 16:17:24
thread:1 rba:(0x4c.19da.10)
--oracle在恢复时最有用的就是Checkpointed at scn:0x0000.001dd76c和
thread:1 rba:(0x4c.19da.10)了
--======================================
DATA FILE #2:
  (name #1) E:\ORACLE\PRODUCT\10.2.0\ORADATA\TEST\TEST.DBF
....................................中间无关内容省略
Checkpointed at scn:  0x0000.001dd76c 10/01/2008 16:17:24
thread:1 rba:(0x4c.19da.10)
--=======================================
DATA FILE #3:
  (name #5) E:\ORACLE\PRODUCT\10.2.0\ORADATA\TEST\SYSAUX01.DBF
....................................中间无关内容省略
Checkpointed at scn:  0x0000.001dd76c 10/01/2008 16:17:24
thread:1 rba:(0x4c.19da.10)
--=======================================
DATA FILE #4:
  (name #6) E:\ORACLE\PRODUCT\10.2.0\ORADATA\TEST\UNDOTBS01.DBF
....................................中间无关内容省略
Checkpointed at scn:  0x0000.001dd76c 10/01/2008 16:17:24
thread:1 rba:(0x4c.19da.10)
--=======================================
--而上面trace file中记录的Checkpointed at scn:0x0000.001dd76c
转化为10进制数:
SQL> select to_number('001dd76c','xxxxxxxx') from dual;

TO_NUMBER('001DD76C','XXXXXXXX')
--------------------------------
                         1955692

而1955692正是我们在最开始备份时记录下来的checkpoint_change#,另外检查点发生的时间其实也是
吻合的:10/01/2008 16:17:24,也许有人说查询:
select checkpoint_change#,checkpoint_time from v$datafile_header;
其实读取的就是数据文件头,结果当然是一样的,呵呵,没错,不论是上面查询还是dump datafile header
其实信息的来源都是来自datafile header。只是dump出来我们看的更加直观一些,其实在数据字典中也提供了
类似的信息,如上面执行的查询:
select hxfil,fhrba_seq,fhrba_bno,fhrba_bof from  x$kcvfh;
为什么要查询x$kcvfh,是因为x$kcvfh是v$datafile_header的源,这个大家可以查看
v$fixed_view_definition而得知。
其实fhrba_seq,fhrba_bno,fhrba_bof这3个字段对应的就是rba,rba的意思是:
Recent entries in the redo thread of an Oracle instance are addressed using a 3-part redo byte address, or RBA. An RBA is comprised of
the log file sequence number (4 bytes)
the log file block number (4 bytes)
the byte offset into the block at which the redo record starts (2 bytes)
在datafile header上记录rba,在恢复时就能非常准确的知道需要哪个日志文件(通过the log file sequence number)以及哪个block(通过the log file block number)以及
在这个日志block上从哪个byte开始读取恢复(通过the byte offset)
--=========================================
下面我们来接着上面打开db时的提示来恢复db,验证一下:
SQL> alter database open;
alter database open
*
第 1 行出现错误:
ORA-01113: 文件 1 需要介质恢复
ORA-01110: 数据文件 1: 'E:\ORACLE\PRODUCT\10.2.0\ORADATA\TEST\SYSTEM01.DBF'


SQL> recover database;
ORA-00279: 更改 1955692 (在 10/01/2008 16:17:24 生成) 对于线程 1 是必需的
ORA-00289: 建议:
E:\ORACLE\PRODUCT\10.2.0\FLASH_RECOVERY_AREA\TEST\ARCHIVELOG\2008_10_01\O1_MF_1_

76_%U_.ARC
ORA-00280: 更改 1955692 (用于线程 1) 在序列 #76 中


指定日志: {<RET>=suggested | filename | AUTO | CANCEL}

--====================================
--这里为什么会从1955692开始恢复db,原因当然就是备份时db发生检查点
其对应的checkpoint_change#是1955692,这个我们在最开始的时候就提到过,说
在备份时会用到这个值:1955692,那么序列#76就是如何来的呢?
其实就是从rba转化来得:备份时候datafile header的dump信息上面已经显示出来了,
其实rba是:thread:1 rba:(0x4c.19da.10)
根据rba表示的意义把4c转化成10进制数不正是:4*16+12(16进制的c)=76
,那么sequence#=76的归档日志文件O1_MF_1_76_%U_.ARC其实并不会在恢复时完全用到,而是从
block:19da转化为10进制数是:
SQL> select to_number('19da','xxxx') from dual;

TO_NUMBER('19DA','XXXX')
------------------------
                    6618
也就是从6618#block开始恢复
下面开始恢复:
--========================================
接着上面要求恢复的提示敲回车:
ORA-00279: 更改 1956233 (在 10/01/2008 16:27:12 生成) 对于线程 1 是必需的
ORA-00289: 建议:
E:\ORACLE\PRODUCT\10.2.0\FLASH_RECOVERY_AREA\TEST\ARCHIVELOG\2008_10_01\O1_MF_1_

77_%U_.ARC
ORA-00280: 更改 1956233 (用于线程 1) 在序列 #77 中
ORA-00278: 此恢复不再需要日志文件
'E:\ORACLE\PRODUCT\10.2.0\FLASH_RECOVERY_AREA\TEST\ARCHIVELOG\2008_10_01\O1_MF_1

_76_4G6F313F_.ARC'


指定日志: {<RET>=suggested | filename | AUTO | CANCEL}

--====================================
sequence#=76的日志已经恢复,接下来需要77#日志:
恢复时到底需要那些归档日志可以通过查看 v$recovery_log来获得:
v$recovery_log的信息就是通过比较control file中的checkpoint_change#
和datafile header上的checkpoint_change#而产生的,如果我们在恢复时
把备份的controlfile和datafile一同拷贝回来(不要拷贝redo),那么肯定在
v$recovery_log不会查到任何信息。
SQL> select sequence# from v$recovery_log;

SEQUENCE#
----------
        77
        78

SQL>
在76#归档日志恢复之后再来观察一下数据文件头上checkpoint_change#和rba的变化情况:
checkpoint_change#信息:
SQL> select checkpoint_change#,checkpoint_time from v$datafile_header;

CHECKPOINT_CHANGE# CHECKPOINT_TIME
------------------ -------------------
           1956233 2008/10/01 16:27:12
           1956233 2008/10/01 16:27:12
           1956233 2008/10/01 16:27:12
           1956233 2008/10/01 16:27:12

SQL>
rba信息:
SQL> select hxfil,fhrba_seq,fhrba_bno,fhrba_bof from  x$kcvfh;

     HXFIL  FHRBA_SEQ  FHRBA_BNO  FHRBA_BOF
---------- ---------- ---------- ----------
         1         77          2          0
         2         77          2          0
         3         77          2          0
         4         77          2          0

SQL>
此时再恢复db时会使用sequence#=77的归档日志,同时是从第二个日志block
开始使用的,因为日志文件头占用1个block,如果有人通过dd命令做过redo file
从文件系统和raw转化的话应该知道redo的头占用1个block,不过这个可能也和os有关的
,不同的os,redo的头块也可能会占用不同个数的block,具体没有做过太深入的研究。
--==========================
接着恢复:
ORA-00279: 更改 1956324 (在 10/01/2008 16:30:40 生成) 对于线程 1 是必需的
ORA-00289: 建议:
E:\ORACLE\PRODUCT\10.2.0\FLASH_RECOVERY_AREA\TEST\ARCHIVELOG\2008_10_01\O1_MF_1_

78_%U_.ARC
ORA-00280: 更改 1956324 (用于线程 1) 在序列 #78 中
ORA-00278: 此恢复不再需要日志文件
'E:\ORACLE\PRODUCT\10.2.0\FLASH_RECOVERY_AREA\TEST\ARCHIVELOG\2008_10_01\O1_MF_1

_77_4G6F9JSW_.ARC'


指定日志: {<RET>=suggested | filename | AUTO | CANCEL}

--==========================
查询一下checkpoint_change#和rba的信息:
上面通过查询view验证过了,这次dump 一下datafile header来看看:
SQL> alter session set events 'immediate trace name FILE_HDRS level 12';

会话已更改。
--=======================
trace file 主要信息:(仅摘录一个文件的信息,4个文件的信息其实都相同)
DATA FILE #1:
  (name #7) E:\ORACLE\PRODUCT\10.2.0\ORADATA\TEST\SYSTEM01.DBF
..........................................(省去无关的信息)
Checkpointed at scn:  0x0000.001dd9e4 10/01/2008 16:30:40
thread:1 rba:(0x4e.2.0)
--=======================
这里只转化一下sequence#:4e看看是否是78就可以了:
4*16+14(16进制的e)=78
正好是78,也就是恢复时下一个要使用的归档日志。
--=============================
接着恢复:
ORA-00279: 更改 1956324 (在 10/01/2008 16:30:40 生成) 对于线程 1 是必需的
ORA-00289: 建议:
E:\ORACLE\PRODUCT\10.2.0\FLASH_RECOVERY_AREA\TEST\ARCHIVELOG\2008_10_01\O1_MF_1_

78_%U_.ARC
ORA-00280: 更改 1956324 (用于线程 1) 在序列 #78 中
ORA-00278: 此恢复不再需要日志文件
'E:\ORACLE\PRODUCT\10.2.0\FLASH_RECOVERY_AREA\TEST\ARCHIVELOG\2008_10_01\O1_MF_1

_77_4G6F9JSW_.ARC'


指定日志: {<RET>=suggested | filename | AUTO | CANCEL}

已应用的日志。
完成介质恢复。
SQL>
--===================================
78#归档日志恢复之后checkpoint_change#可以达到1956480,通过下面查询78#
归档日志的next_change#可以得知:
SQL> select sequence#,first_change#,next_change#  from v$archived_log
  2  where sequence# in (76,77,78) and resetlogs_id=666280390;

SEQUENCE# FIRST_CHANGE# NEXT_CHANGE#
---------- ------------- ------------
        76       1951985      1956233
        77       1956233      1956324
        78       1956324      1956480

SQL>
但目前datafile header的checkpoint_change#和rba信息是:
1967624以及81       1281         16,是因为在恢复时系统
自动读取了联机日志。
SQL> select checkpoint_change#,checkpoint_time from v$datafile_header;

CHECKPOINT_CHANGE# CHECKPOINT_TIME
------------------ -------------------
           1967624 2008/10/01 19:06:21
           1967624 2008/10/01 19:06:21
           1967624 2008/10/01 19:06:21
           1967624 2008/10/01 19:06:21

SQL> select hxfil,fhrba_seq,fhrba_bno,fhrba_bof from  x$kcvfh;

     HXFIL  FHRBA_SEQ  FHRBA_BNO  FHRBA_BOF
---------- ---------- ---------- ----------
         1         81       1281         16
         2         81       1281         16
         3         81       1281         16
         4         81       1281         16

SQL> select group#,status,sequence#,archived,first_change# from v$log;

    GROUP# STATUS            SEQUENCE# ARC FIRST_CHANGE#
---------- ---------------- ---------- --- -------------
         1 INACTIVE                 80 YES       1961750
         3 CURRENT                  81 NO        1967088
         2 INACTIVE                 79 YES       1956480

SQL>
--oracle为什么能自动读取redo来恢复,是因为在controlfile中记录了redo的信息
SQL> select sequence#,checkpoint_change#,last_redo_change# from v$thread;

SEQUENCE# CHECKPOINT_CHANGE# LAST_REDO_CHANGE#
---------- ------------------ -----------------
        81            1967625           1967375

SQL>
--下面把最新的redo暂时隐藏起来,也就是说不让其自动应用redo再来观查一下
oracle是如何要寻找redo的:
SQL> shutdown immediate
ORA-01109: 数据库未打开


已经卸载数据库。
ORACLE 例程已经关闭。
--拷贝备份的数据文件,同时把redo隐藏起来
SQL> startup
ORACLE 例程已经启动。

Total System Global Area  163577856 bytes
Fixed Size                  1247876 bytes
Variable Size              92276092 bytes
Database Buffers           67108864 bytes
Redo Buffers                2945024 bytes
数据库装载完毕。
ORA-01113: 文件 1 需要介质恢复
ORA-01110: 数据文件 1: 'E:\ORACLE\PRODUCT\10.2.0\ORADATA\TEST\SYSTEM01.DBF'


SQL> recover database;
ORA-00279: 更改 1955692 (在 10/01/2008 16:17:24 生成) 对于线程 1 是必需的
ORA-00289: 建议:
E:\ORACLE\PRODUCT\10.2.0\FLASH_RECOVERY_AREA\TEST\ARCHIVELOG\2008_10_01\O1_MF_1_

76_%U_.ARC
ORA-00280: 更改 1955692 (用于线程 1) 在序列 #76 中


指定日志: {<RET>=suggested | filename | AUTO | CANCEL}

ORA-00279: 更改 1956233 (在 10/01/2008 16:27:12 生成) 对于线程 1 是必需的
ORA-00289: 建议:
E:\ORACLE\PRODUCT\10.2.0\FLASH_RECOVERY_AREA\TEST\ARCHIVELOG\2008_10_01\O1_MF_1_

77_%U_.ARC
ORA-00280: 更改 1956233 (用于线程 1) 在序列 #77 中
ORA-00278: 此恢复不再需要日志文件
'E:\ORACLE\PRODUCT\10.2.0\FLASH_RECOVERY_AREA\TEST\ARCHIVELOG\2008_10_01\O1_MF_1

_76_4G6F313F_.ARC'


指定日志: {<RET>=suggested | filename | AUTO | CANCEL}

ORA-00279: 更改 1956324 (在 10/01/2008 16:30:40 生成) 对于线程 1 是必需的
ORA-00289: 建议:
E:\ORACLE\PRODUCT\10.2.0\FLASH_RECOVERY_AREA\TEST\ARCHIVELOG\2008_10_01\O1_MF_1_

78_%U_.ARC
ORA-00280: 更改 1956324 (用于线程 1) 在序列 #78 中
ORA-00278: 此恢复不再需要日志文件
'E:\ORACLE\PRODUCT\10.2.0\FLASH_RECOVERY_AREA\TEST\ARCHIVELOG\2008_10_01\O1_MF_1

_77_4G6F9JSW_.ARC'


指定日志: {<RET>=suggested | filename | AUTO | CANCEL}

ORA-00283: 恢复会话因错误而取消
ORA-00313: 无法打开日志组 2 (用于线程 1) 的成员
ORA-00312: 联机日志 2 线程 1:
'E:\ORACLE\PRODUCT\10.2.0\ORADATA\TEST\REDO02.LOG'
ORA-27041: 无法打开文件
OSD-04002: 无法打开文件
O/S-Error: (OS 2) 系统找不到指定的文件。


ORA-01112: 未启动介质恢复
--oracle为什么会找REDO02.LOG,因为REDO02.LOG对应的sequence#是79,看看在controlfile中记录的redo信息就知道了
,v$log的信息来自controlfile,这也说明了为什么我们在恢复db时如果controlfile是最新的话那么在恢复时redo会被自动应用,而
当controlfile是从备份中恢复过来(也就是说controlfile不是最新的,是备份的,在恢复时需要使用using backup controlfile子句)
的话在恢复db时redo不会被自动应用,而需要我们手动输入来尝试看看oracle到底需要哪个redo

SQL> select group#,status,sequence#,first_change# from v$log;

    GROUP# STATUS            SEQUENCE# FIRST_CHANGE#
---------- ---------------- ---------- -------------
         1 INACTIVE                 80       1961750
         3 CURRENT                  81       1967088
         2 INACTIVE                 79       1956480

SQL>
--============================
验证一下使用using backup controlfile自己恢复db时使用redo的情况:
SQL> shutdown immediate
ORA-01109: 数据库未打开


已经卸载数据库。
ORACLE 例程已经关闭。
SQL>
--拷贝备份的datafile and controlfile以及最新的redo回来
SQL> startup
ORACLE 例程已经启动。

Total System Global Area  163577856 bytes
Fixed Size                  1247876 bytes
Variable Size              92276092 bytes
Database Buffers           67108864 bytes
Redo Buffers                2945024 bytes
数据库装载完毕。
ORA-00314: 日志 1 (用于线程 1) 要求的序号  与  不匹配
ORA-00312: 联机日志 1 线程 1:
'E:\ORACLE\PRODUCT\10.2.0\ORADATA\TEST\REDO01.LOG'


SQL>
为什么在open db时会发出这样的提示:
看看controlfile and datafile_header中记录的checkpoint_change#:
SQL> select checkpoint_change# from v$database;

CHECKPOINT_CHANGE#
------------------
           1955692

SQL> select checkpoint_change#,checkpoint_time from v$datafile_header;

CHECKPOINT_CHANGE# CHECKPOINT_TIME
------------------ -------------------
           1955692 2008/10/01 16:17:24
           1955692 2008/10/01 16:17:24
           1955692 2008/10/01 16:17:24
           1955692 2008/10/01 16:17:24

SQL> select checkpoint_change#,checkpoint_time from v$datafile;

CHECKPOINT_CHANGE# CHECKPOINT_TIME
------------------ -------------------
           1955692 2008/10/01 16:17:24
           1955692 2008/10/01 16:17:24
           1955692 2008/10/01 16:17:24
           1955692 2008/10/01 16:17:24

SQL> select checkpoint_change#,checkpoint_time from v$thread;

CHECKPOINT_CHANGE# CHECKPOINT_TIME
------------------ -------------------
           1955692 2008/10/01 16:17:24

SQL> select hxfil,fhrba_seq,fhrba_bno,fhrba_bof from  x$kcvfh;

     HXFIL  FHRBA_SEQ  FHRBA_BNO  FHRBA_BOF
---------- ---------- ---------- ----------
         1         76       6618         16
         2         76       6618         16
         3         76       6618         16
         4         76       6618         16

SQL> select group#,status,sequence#, first_change# from v$log;

    GROUP# STATUS            SEQUENCE# FIRST_CHANGE#
---------- ---------------- ---------- -------------
         1 INACTIVE                 74       1926639
         3 INACTIVE                 75       1947901
         2 CURRENT                  76       1951985
--很显然v$log的信息是来自controlfile的,和上面新的controlfile中记录的
v$log的信息对比,当然doc上也明确提到v$log的信息来自controlfile
从上面的查询看出来controlfile和datafile中记录的checkpoint_change#都是1955692
,而且controlfile中记录的redo的checkpoint_change#也是1955692;但是再来看看redo中记录的
checkpoint_change#又是多少呢?
我发现redo header上并不会记录checkpoint_change#,这一点大家可以验证,当然
当checkpoint发生时很多doc上都提到会把当前的scn更新到controlfile和datafile header上,
并没有提到会更新再redo的头上。
SQL> alter session set events 'immediate trace name REDOHDR level 12';

会话已更改。

SQL>
从下面的trace file中我们知道大致判断LOG FILE #1(#2,#3)这一段的信息
和controlfile中记录的一致,我在这里认定LOG FILE #1(#2,#3)这段信息是来自controlfile中:从seq(sequence#)就可以判断出来:0x0000004a,0x0000004c,0x0000004b
分别对应10进制的74,76,75,而且LOG FILE #2的Next scn: 0xffff.ffffffff,说明它表示是当前redo,这些内容都和controlfile中记录的完全一致;
但是从 FILE HEADER:这一段开始发现它的内容才是真真来自redo:
因为LOG FILE #1(#2,#3)对应的Seq#分别是: 0000000080,0000000079,0000000081
而且LOG FILE #3的Next scn: 0xffff.ffffffff,说明它表示是当前redo
那么在redo的header上是否记录controlfile的信息呢,应该不记录,这里是这条命令:
alter session set events 'immediate trace name REDOHDR level 12';执行时要
从controlfile里读取redo的路径以及一些相关信息(就是LOG FILE #1(#2,#3)这一段)从而再到redo的header上真真
读取redo的内容。由于controlfile中记录的redo的信息和redo header上记录的信息不符,所以打开db时出现了上面的提示:
"ORA-00314: 日志 1 (用于线程 1) 要求的序号  与  不匹配
ORA-00312: 联机日志 1 线程 1:
'E:\ORACLE\PRODUCT\10.2.0\ORADATA\TEST\REDO01.LOG'"

trace file的信息如下:
--==================================
LOG FILE #1:
  (name #2) E:\ORACLE\PRODUCT\10.2.0\ORADATA\TEST\REDO01.LOG
Thread 1 redo log links: forward: 2 backward: 0
siz: 0x2000 seq: 0x0000004a hws: 0x4 bsz: 512 nab: 0x4eb flg: 0x1 dup: 1
Archive links: fwrd: 0 back: 0 Prev scn: 0x0000.001d6386
Low scn: 0x0000.001d65ef 09/30/2008 23:04:54
Next scn: 0x0000.001db8fd 10/01/2008 12:59:45
FILE HEADER:
        Compatibility Vsn = 169869568=0xa200100
        Db ID=1963034992=0x75018970, Db Name='TEST'
        Activation ID=1964389871=0x751635ef
        Control Seq=3855=0xf0f, File size=8192=0x2000
        File Number=1, Blksiz=512, File Type=2 LOG
descrip:"Thread 0001, Seq# 0000000080, SCN 0x0000001def16-0x0000001e03f0"
thread: 1 nab: 0x1ffd seq: 0x00000050 hws: 0x2 eot: 0 dis: 0
reset logs count: 0x27b6a1c6 scn: 0x0000.0015dd61
Low scn: 0x0000.001def16 10/01/2008 17:16:54
Next scn: 0x0000.001e03f0 10/01/2008 19:00:41
Enabled scn: 0x0000.0015dd61 09/24/2008 13:53:10
Thread closed scn: 0x0000.001def16 10/01/2008 17:16:54
Disk cksum: 0x2a74 Calc cksum: 0x2a74
Terminal Recovery Stop scn: 0x0000.00000000
Terminal Recovery Stamp  01/01/1988 00:00:00
Most recent redo scn: 0x0000.00000000
Largest LWN: 315 blocks
Miscellaneous flags: 0x0
Thread internal enable indicator: thr: 0, seq: 0 scn: 0x0000.00000000
LOG FILE #2:
  (name #3) E:\ORACLE\PRODUCT\10.2.0\ORADATA\TEST\REDO02.LOG
Thread 1 redo log links: forward: 3 backward: 1
siz: 0x2000 seq: 0x0000004c hws: 0x2 bsz: 512 nab: 0x19da flg: 0x8 dup: 1
Archive links: fwrd: 0 back: 0 Prev scn: 0x0000.001db8fd
Low scn: 0x0000.001dc8f1 10/01/2008 14:17:00
Next scn: 0xffff.ffffffff 01/01/1988 00:00:00
FILE HEADER:
        Compatibility Vsn = 169869568=0xa200100
        Db ID=1963034992=0x75018970, Db Name='TEST'
        Activation ID=1964389871=0x751635ef
        Control Seq=3850=0xf0a, File size=8192=0x2000
        File Number=2, Blksiz=512, File Type=2 LOG
descrip:"Thread 0001, Seq# 0000000079, SCN 0x0000001dda80-0x0000001def16"
thread: 1 nab: 0x1ffd seq: 0x0000004f hws: 0x2 eot: 0 dis: 0
reset logs count: 0x27b6a1c6 scn: 0x0000.0015dd61
Low scn: 0x0000.001dda80 10/01/2008 16:35:11
Next scn: 0x0000.001def16 10/01/2008 17:16:54
Enabled scn: 0x0000.0015dd61 09/24/2008 13:53:10
Thread closed scn: 0x0000.001dda80 10/01/2008 16:35:11
Disk cksum: 0xe55a Calc cksum: 0xe55a
Terminal Recovery Stop scn: 0x0000.00000000
Terminal Recovery Stamp  01/01/1988 00:00:00
Most recent redo scn: 0x0000.00000000
Largest LWN: 227 blocks
Miscellaneous flags: 0x0
Thread internal enable indicator: thr: 0, seq: 0 scn: 0x0000.00000000
LOG FILE #3:
  (name #4) E:\ORACLE\PRODUCT\10.2.0\ORADATA\TEST\REDO03.LOG
Thread 1 redo log links: forward: 0 backward: 2
siz: 0x2000 seq: 0x0000004b hws: 0x3 bsz: 512 nab: 0x1ffd flg: 0x1 dup: 1
Archive links: fwrd: 0 back: 0 Prev scn: 0x0000.001d65ef
Low scn: 0x0000.001db8fd 10/01/2008 12:59:45
Next scn: 0x0000.001dc8f1 10/01/2008 14:17:00
FILE HEADER:
        Compatibility Vsn = 169869568=0xa200100
        Db ID=1963034992=0x75018970, Db Name='TEST'
        Activation ID=1964389871=0x751635ef
        Control Seq=3859=0xf13, File size=8192=0x2000
        File Number=3, Blksiz=512, File Type=2 LOG
descrip:"Thread 0001, Seq# 0000000081, SCN 0x0000001e03f0-0xffffffffffff"
thread: 1 nab: 0x501 seq: 0x00000051 hws: 0x2 eot: 1 dis: 0
reset logs count: 0x27b6a1c6 scn: 0x0000.0015dd61
Low scn: 0x0000.001e03f0 10/01/2008 19:00:41
Next scn: 0xffff.ffffffff 01/01/1988 00:00:00
Enabled scn: 0x0000.0015dd61 09/24/2008 13:53:10
Thread closed scn: 0x0000.001e0609 10/01/2008 19:06:21
Disk cksum: 0x9c26 Calc cksum: 0x9c26
Terminal Recovery Stop scn: 0x0000.00000000
Terminal Recovery Stamp  01/01/1988 00:00:00
Most recent redo scn: 0x0000.00000000
Largest LWN: 219 blocks
Miscellaneous flags: 0x0
Thread internal enable indicator: thr: 0, seq: 0 scn: 0x0000.00000000
--=============================================
下面恢复一下db:
SQL> recover database using backup controlfile;
ORA-00279: 更改 1955692 (在 10/01/2008 16:17:24 生成) 对于线程 1 是必需的
ORA-00289: 建议:
E:\ORACLE\PRODUCT\10.2.0\FLASH_RECOVERY_AREA\TEST\ARCHIVELOG\2008_10_01\O1_MF_1_

76_%U_.ARC
ORA-00280: 更改 1955692 (用于线程 1) 在序列 #76 中


指定日志: {<RET>=suggested | filename | AUTO | CANCEL}
auto
ORA-00279: 更改 1956233 (在 10/01/2008 16:27:12 生成) 对于线程 1 是必需的
ORA-00289: 建议:
E:\ORACLE\PRODUCT\10.2.0\FLASH_RECOVERY_AREA\TEST\ARCHIVELOG\2008_10_01\O1_MF_1_

77_%U_.ARC
ORA-00280: 更改 1956233 (用于线程 1) 在序列 #77 中
ORA-00278: 此恢复不再需要日志文件
'E:\ORACLE\PRODUCT\10.2.0\FLASH_RECOVERY_AREA\TEST\ARCHIVELOG\2008_10_01\O1_MF_1

_76_4G6F313F_.ARC'


ORA-00279: 更改 1956324 (在 10/01/2008 16:30:40 生成) 对于线程 1 是必需的
ORA-00289: 建议:
E:\ORACLE\PRODUCT\10.2.0\FLASH_RECOVERY_AREA\TEST\ARCHIVELOG\2008_10_01\O1_MF_1_

78_%U_.ARC
ORA-00280: 更改 1956324 (用于线程 1) 在序列 #78 中
ORA-00278: 此恢复不再需要日志文件
'E:\ORACLE\PRODUCT\10.2.0\FLASH_RECOVERY_AREA\TEST\ARCHIVELOG\2008_10_01\O1_MF_1

_77_4G6F9JSW_.ARC'


ORA-00279: 更改 1956480 (在 10/01/2008 16:35:11 生成) 对于线程 1 是必需的
ORA-00289: 建议:
E:\ORACLE\PRODUCT\10.2.0\FLASH_RECOVERY_AREA\TEST\ARCHIVELOG\2008_10_01\O1_MF_1_

79_%U_.ARC
ORA-00280: 更改 1956480 (用于线程 1) 在序列 #79 中
ORA-00278: 此恢复不再需要日志文件
'E:\ORACLE\PRODUCT\10.2.0\FLASH_RECOVERY_AREA\TEST\ARCHIVELOG\2008_10_01\O1_MF_1

_78_4G6FL06C_.ARC'


ORA-00279: 更改 1961750 (在 10/01/2008 17:16:54 生成) 对于线程 1 是必需的
ORA-00289: 建议:
E:\ORACLE\PRODUCT\10.2.0\FLASH_RECOVERY_AREA\TEST\ARCHIVELOG\2008_10_01\O1_MF_1_

80_%U_.ARC
ORA-00280: 更改 1961750 (用于线程 1) 在序列 #80 中
ORA-00278: 此恢复不再需要日志文件
'E:\ORACLE\PRODUCT\10.2.0\FLASH_RECOVERY_AREA\TEST\ARCHIVELOG\2008_10_01\O1_MF_1

_79_4G6J06PY_.ARC'


ORA-00279: 更改 1967088 (在 10/01/2008 19:00:41 生成) 对于线程 1 是必需的
ORA-00289: 建议:
E:\ORACLE\PRODUCT\10.2.0\FLASH_RECOVERY_AREA\TEST\ARCHIVELOG\2008_10_01\O1_MF_1_

81_%U_.ARC
ORA-00280: 更改 1967088 (用于线程 1) 在序列 #81 中
ORA-00278: 此恢复不再需要日志文件
'E:\ORACLE\PRODUCT\10.2.0\FLASH_RECOVERY_AREA\TEST\ARCHIVELOG\2008_10_01\O1_MF_1

_80_4G6P2T6T_.ARC'


ORA-00308: 无法打开归档日志
'E:\ORACLE\PRODUCT\10.2.0\FLASH_RECOVERY_AREA\TEST\ARCHIVELOG\2008_10_01\O1_MF_1

_81_%U_.ARC'
ORA-27041: 无法打开文件
OSD-04002: 无法打开文件
O/S-Error: (OS 2) 系统找不到指定的文件。


SQL>
SQL> select hxfil,fhrba_seq,fhrba_bno,fhrba_bof from  x$kcvfh;

     HXFIL  FHRBA_SEQ  FHRBA_BNO  FHRBA_BOF
---------- ---------- ---------- ----------
         1         81          2          0
         2         81          2          0
         3         81          2          0
         4         81          2          0
SQL> select sequence#,last_redo_sequence# from v$thread;

SEQUENCE# LAST_REDO_SEQUENCE#
---------- -------------------
        76                  76

SQL>
--目前datafile header上的sequence#是81,也就是恢复db接下来需要的redo sequence#是81,也就是当前redo:group 3;
而controlfile中记录的是76,因此当controlfile不是最新时,此时恢复db是无法自动应用redo,就是这个道理,
需要我们挨个输入redo来尝试,当然前面已经对redo的header进行了dump,我们
知道81的redo是group 3,接着恢复,并且输入group 3对应的redo的路径和名称:
SQL> recover database using backup controlfile;
ORA-00279: 更改 1967088 (在 10/01/2008 19:00:41 生成) 对于线程 1 是必需的
ORA-00289: 建议:
E:\ORACLE\PRODUCT\10.2.0\FLASH_RECOVERY_AREA\TEST\ARCHIVELOG\2008_10_01\O1_MF_1_

81_%U_.ARC
ORA-00280: 更改 1967088 (用于线程 1) 在序列 #81 中


指定日志: {<RET>=suggested | filename | AUTO | CANCEL}
E:\oracle\product\10.2.0\oradata\test\redo03.log
已应用的日志。
完成介质恢复。
SQL> alter database open  resetlogs;

数据库已更改。

SQL>


文章出处:[url]http://www.itpub.net/thread-1065138-1-1.html[/url]

你可能感兴趣的:(数据库,职场,备份恢复,休闲)