揭密備份恢復的原理
其實一句話就可以說明白:那就是資料檔案的頭上不僅包含了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 中
指定日誌: {=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'
指定日誌: {=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'
指定日誌: {=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'
指定日誌: {=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 中
指定日誌: {=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'
指定日誌: {=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'
指定日誌: {=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 中
指定日誌: {=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 中
指定日誌: {=suggested | filename | AUTO | CANCEL}
E:\oracle\product\10.2.0\oradata\test\redo03.log
已應用的日誌。
完成介質恢復。
SQL> alter database open resetlogs;
資料庫已更改。
文章出處:http://www.itpub.net/thread-1065138-1-1.html
結果花了很大篇幅,只想以試驗的方式做個簡單的驗證,便於大家理解。歡迎拍磚!
另外提個問題:是否存在一些資料字典它是源於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 中
指定日誌: {
--====================================
--這裡為什麼會從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'
指定日誌: {
--====================================
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'
指定日誌: {
--==========================
上面透過查詢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'
指定日誌: {
已應用的日誌。
完成介質恢復。
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 中
指定日誌: {
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-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 中
指定日誌: {
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>
而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 中
指定日誌: {
E:\oracle\product\10.2.0\oradata\test\redo03.log
已應用的日誌。
完成介質恢復。
SQL> alter database open resetlogs;
資料庫已更改。
文章出處:http://www.itpub.net/thread-1065138-1-1.html
來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/22664653/viewspace-664520/,如需轉載,請註明出處,否則將追究法律責任。
相關文章
- Xtrabackup備份恢復原理
- RMAN備份恢復原理
- 備份恢復原理的實踐
- oracle備份恢復的大致原理!Oracle
- 備份與恢復--利用備份的控制檔案恢復
- 【備份恢復】從備份恢復資料庫資料庫
- 【管理篇備份恢復】備份恢復基礎
- Oracle備份恢復之熱備份恢復及異機恢復Oracle
- 備份與恢復系列 十一 控制檔案的備份與恢復
- MySQL備份與恢復——基於Xtrabackup物理備份恢復MySql
- Mysql備份恢復MySql
- Postgresql 備份恢復SQL
- redis備份恢復Redis
- mysql 備份恢復MySql
- 備份和恢復
- 備份&恢復之四:非歸檔模式下的備份與恢復模式
- 備份與恢復:polardb資料庫備份與恢復資料庫
- 【備份恢復】Oracle 資料備份與恢復微實踐Oracle
- Mysql的備份與恢復MySql
- Backup And Recovery User's Guide-備份和恢復概覽-備份和恢復介紹-備份和恢復的目的GUIIDE
- 備份與恢復系列 十 引數檔案spfile的備份與恢復
- 備份與恢復--從備份的歸檔日誌中恢復資料
- 【物理熱備】(下)備份恢復系統表空間 手工備份恢復
- 詳解叢集級備份恢復:物理細粒度備份恢復
- 【備份恢復】noarchive模式下使用增量備份恢復資料庫Hive模式資料庫
- windwos server 路由備份和恢復 路由表備份和恢復Server路由
- 【備份恢復】資料恢復指導資料恢復
- Mysql備份與恢復(1)---物理備份MySql
- RMAN備份與恢復之加密備份加密
- RMAN備份恢復——備份到帶庫的效能
- Grafana 備份恢復教程Grafana
- redis 備份和恢復Redis
- Postgresql 備份與恢復SQL
- Nifi flow 備份恢復Nifi
- 備份和恢復redisRedis
- MySQL備份與恢復MySql
- Oracle 備份恢復概念Oracle
- Mysql備份和恢復MySql