1. 程式人生 > >Oracle SCN機制解析

Oracle SCN機制解析

丟失 self pen 必須 發出 span system 幫助 不同的

SCN(System Chang Number)作為oracle中的一個重要機制,在數據恢復、Data Guard、Streams復制、RAC節點間的同步等各個功能中起著重要作用。理解SCN的運作機制,可以幫助你更加深入地了解上述功能。

在理解SCN之前,我們先看下oracle事務中的數據變化是如何寫入數據文件的:

1、事務開始;

2、buffer cache中找到需要的數據塊,如果沒有找到,則從數據文件中載入buffer cache中;

3、事務修改buffer cache的數據塊,該數據被標識為“臟數據”,並被寫入log buffer中;

4、事務提交,LGWR進程將log buffer中的“臟數據”寫入redo log file中;

5、當發生checkpoint,CKPT進程更新所有數據文件的文件頭中的信息,DBWn進程則負責將Buffer Cache中的臟數據寫入到數據文件中。

經過上述5 個步驟,事務中的數據變化最終被寫入到數據文件中。但是,一旦在上述中間環節時,數據庫意外宕機了,在重新啟動時如何知道哪些數據已經寫入數據文件、哪些 沒有寫呢(同樣,在DG、streams中也存在類似疑問:redo log中哪些是上一次同步已經復制過的數據、哪些沒有)?SCN機制就能比較完善的解決上述問題。

SCN是一個數字,確切的說是一個只會增加、不會減少的數字。正是它這種只會增加的特性確保了Oracle知道哪些應該被恢復、哪些應該被復制。

總共有4 中SCN:系統檢查點(System Checkpoint)SCN、數據文件檢查點(Datafile Checkpoint)SCN、結束SCN(Stop SCN)、開始SCN(Start SCN)。其中其面3中SCN存在於控制文件中,最後一種則存在於數據文件的文件頭中。

在控制文件中,System Checkpoint SCN是針對整個數據庫全局的,因而之存在一個,而Datafile Checkpoint SCN和Stop SCN是針對每個數據文件的,因而一個數據文件就對應在控制文件中存在一份Datafile Checkpoint SCN和Stop SCN。在數據庫正常運行期間,Stop SCN(通過視圖v$datafile的字段last_change#可以查詢)是一個無窮大的數字或者說是NULL。

在一個事務提交後(上述第四個步驟),會在redo log中存在一條redo記錄,同時,系統為其提供一個最新的SCN(通過函數 dbms_flashback.get_system_change_number可以知道當前的最新SCN),記錄在該條記錄中。如果該條記錄是在 redo log被清空(日誌滿做切換時或發生checkpoint時,所有變化日誌已經被寫入數據文件中),則其SCN被記錄為redo log的low SCN。以後在日誌再次被清空前寫入的redo記錄中SCN則成為Next SCN。

當日誌切換或發生checkpoint(上 述第五個步驟)時,從Low SCN到Next SCN之間的所有redo記錄的數據就被DBWn進程寫入數據文件中,而CKPT進程則將所有數據文件(無論redo log中的數據是否影響到該數據文件)的文件頭上記錄的Start SCN(通過視圖v$datafile_header的字段checkpoint_change#可以查詢)更新為Next SCN,同時將控制文件中的System Checkpoint SCN(通過視圖v$database的字段checkpoint_change#可以查詢)、每個數據文件對應的Datafile Checkpoint(通過視圖v$datafile的字段checkpoint_change#可以查詢)也更新為Next SCN。但是,如果該數據文件所在的表空間被設置為read-only時,數據文件的Start SCN和控制文件中Datafile Checkpoint SCN都不會被更新。

那系統是如何產生一個最新的SCN 的?實際上,這個數字是由當時的timestamp轉換過來的。每當需要產生一個最新的SCN到redo記錄時,系統獲取當時的timestamp,將其 轉換為數字作為SCN。我們可以通過函數SCN_TO_TIMESTAMP(10g以後)將其轉換回timestamp:

SQL> select dbms_flashback.get_system_change_number, SCN_TO_TIMESTAMP(dbms_flashback.get_system_change_number) from dual;
 
GET_SYSTEM_CHANGE_NUMBER
------------------------
SCN_TO_TIMESTAMP(DBMS_FLASHBACK.GET_SYSTEM_CHANGE_NUMBER)
---------------------------------------------------------------------------
              2877076756
17-AUG-07 02.15.26.000000000 PM

也可以用函數timestamp_to_scn將一個timestamp轉換為SCN

SQL> select timestamp_to_scn(SYSTIMESTAMP) as scn from dual;
 
       SCN
----------
2877078439

最後,SCN除了作為反映事務數據變化並保持同步外,它還起到系統的“心跳”作用——每隔3秒左右系統會刷新一次系統SCN。

下面,在簡單介紹一下SCN如何在數據庫恢復中起作用。

數據庫在正常關閉(shutdown immediate/normal)時,會先做一次checkpoint,將log file中的數據寫入數據文件中,將控制文件、數據文件中的SCN(包括控制文件中的Stop SCN)都更新為最新的SCN。

數據庫異常/意外關閉不會或者只更新部分Stop SCN。

當數據庫啟動時,Oracle 先檢查控制文件中的每個Datafile Checkpoint SCN和數據文件中的Start SCN是否相同,再檢查每個Datafile Checkpoint SCN和Stop SCN是否相同。如果發現有不同,就從Redo Log中找到丟失的SCN,重新寫入數據文件中進行恢復。具體的數據恢復過程這裏就不再贅述。

SCN作為Oracle中的一個重要機制,在多個重要功能中起著“控制器”的作用。了解SCN的產生和實現方式,幫助DBA理解和處理恢復、DG、Streams復制的問題。

最後提一句,利用SCN機制,在Oracle10g、11g中又增加了一些很實用的功能——數據庫閃回、數據庫負載重現等。

首先這裏我們先介紹四個SCN概念。
1、系統檢查點scn
當一個檢查點動作完成後,Oracle就把系統檢查點的SCN存儲到控制文件中。
select checkpoint_change# from v$database;
2,數據文件檢查點scn
當一個檢查點動作完成後,Oracle就把每個數據文件的scn單獨存放在控制文件中。
select name,checkpoint_change# from v$datafile;
3,啟動scn
Oracle把這個檢查點的scn存儲在每個數據文件的文件頭中,這個值稱為啟動scn,因為它用於在數據庫實例啟動時,
檢查是否需要執行數據庫恢復
select name,checkpoint_change# from v$datafile_header
4、終止scn
每個數據文件的終止scn都存儲在控制文件中。
select name,last_change# from v$datafile

以下條件需要使用using backup controlfile
1)、使用備份控制文件
2)、重建resetlogs控制文件,如果重建立noresetlogs不必要使用using backup controlfile


2、alter database open resetlog
指定RESETLOGS將重設當前LOG sequence number為1,拋棄所有日誌信息。
以下條件需要使用resetlog
1)在不完全恢復(介質恢復)
2)使用備份控制文件
使用resetlogs打開數據庫後無必完整地備份一次數據庫。
3、create controlfile resetlogs/noresetlogs
1).用Noresetlogs重建控制文件時,控制文件中 datafile Checkpoint來自Online logs中的Current log頭
2).用Resetlogs重建控制文件時,控制文件中datafile Checkpoint來自各數據文件頭。

當system scn,datafile scn,start scn 不全相等,需要介質恢復,如果stopscn null需要實例恢復
resetlogs拋棄所有在上一次恢復沒有用到的日誌信息,確保不被重新用與恢復。
1、系統正常關閉:
system scn=datafile scn=start scn=stop scn
1)system scn=datafile scn=start scn,不需要介質恢復
2)stopscn not null,不需要實例恢復
2、系統異常關閉:
system scn=datafile scn=start scn,stop scn null
1)system scn=datafile scn=start scn,不需要介質恢復
2)stopscn null,需要實例恢復
3、舊數據文件
system scn=datafile scn>start scn,stop scn null/notnull
1)system scn=datafile scn>start scn,需要介質恢復成system scn=datafile scn=start scn
2)stopscn null,需要實例恢復,not null 不需要實例恢復
4、備份控制文件
system scn=datafile scn<=start scn(當數據文件為舊的相等),stop scn notnull/null
1)system scn=datafile scn<=start scn,需要使用using backup controlfile介質恢復成system scn=datafile scn=start scn=current log scn(當前日誌最大SCN)
2)為保證上一次恢復沒有用到log日誌不被使用,必須resetlogs
5、重建noresetlogs控制文件
控制文件中 datafile Checkpoint來自Online logs中的Current log頭
current log scn=system scn=datafile scn>=start scn,stop scn not null/null
1)current log scn=system scn=datafile scn>=start scn,需要介質恢復成system scn=datafile scn=start scn=redolog scn(當前日誌最大SCN),stop scn not null
2)stopscn not null 不需要實例恢復
6、重建resetlogs控制文件
控制文件中datafile Checkpoint來自各數據文件頭。
system scn>=datafile scn=start scn,stop scn not null/null
1)system scn>=datafile scn=start scn,需要使用using backup controlfile介質恢復成system scn=datafile scn=start scn(當前日誌最大SCN),stop scn not null
2)stop notnull,因為SCN已經為redolog scn,log已經不能使用,必須resetlogs

目錄

1SCN的介紹

2SCN的工作機制

3SCN的增加

4、其他的SCN

5測試

6小結

7問題

1SCN的介紹


Oracle中的SCN有下面幾種:

1)系統檢查點scn(v$database(checkpoint_change#))

當一個檢查點動作完成之後,Oracle就把系統檢查點的SCN存儲到控制文件中

select checkpoint_change# from v$database;

2)數據文件檢查點scn (v$datafile(checkpoint_change#))

當一個檢查點動作完成之後,Oracle就把每個數據文件的scn單獨存放在控制文件中

select name,checkpoint_change# from v$datafile;

3)數據文件終止scn (v$datafile(last_change#))

每個數據文件的終止scn都存儲在控制文件中。在正常的數據庫操作過程中,所有正處於聯機讀寫模式下的數據文件的終止scn都為null,異常關閉後的Stop SCN,也為NULL.

select name,last_change# from v$datafile;

4)數據文件啟動scn (v$datafile_header(checkpoint_change#)

Oracle把這個檢查點的scn存儲在每個數據文件的文件頭中,這個值稱為啟動scn,因為它用於在數據庫實例啟動時,檢查是否需要執行數據庫恢復

select name,checkpoint_change# from v$datafile_header;

2SCN的工作機制

1)在數據庫打開並運行之後,控制文件中的系統檢查點scn、控制文件中的數據文件檢查點scn和每個數據文件頭中的啟動scn都是相同的

2 )控制文件中的每個數據文件的終止scn都為null

3) NORMALIMMEDIATE關閉數據庫的過程中,系統會執行一個檢查點動作,這時所有數據文件的終止scn都會設置成數據文件頭中的那個啟動scn的值。

4)在數據庫重新啟動的時,Oracle將執行兩次檢查

◆看數據文件頭中的ckpt計數器(v$datafile_header.checkpoint_count)是否與對應控制文件中的ckpt計數器(v$datafile.)一致。若相等,進行第二次檢查

◆比較文件頭中的啟動scn和對應控制文件中的終止scn進行比較,如果終止scn等於啟動scn,則不需要對那個文件進行恢復

5)數據庫打開之後,存儲在控制文件中的數據文件終止scn的值再次被更改為null,這表示數據文件已經打開並能夠正常使用了

註:當ABORT強制關閉數據庫時不進行檢查點處理,所以終止scn仍然為無窮大。在下次啟動期間,發現啟動scn和終止scn不同,需要進行線程恢復。

3SCN的增加

1) SCN(System Change Number)只要數據庫被修改,就會+1,而不是一定要進行checkpoint,例如DML的發生即使沒有提交也會使SCN+1.(哪些情況下SCN會發生變化?)

註:SCN增加並不代表會在數據文件頭中表現出來,而是需要等到checkpoint執行後才寫入(當然可能已經增加了很多)

2)如果一個DML導致產生事務,則會產生一個SCN。這個意思是說如果一個事務包含多個dml,則只有第一個初始產生事務的dml產生scn,提交的時候又是一個scn,如果一個事務只有一個dml,那看起來就是dml產生一個scn,提交或者回滾產生一個scn

3) Oracle10g內部的SCN會默認不管有沒有動作,每隔3s自動增加一次。其他需要增加的情況則再加。

4)只有ckpt進程才會修改文件頭中的checkpoint計數器和SCNDBWR只會修改數據塊,即ckpt通知dbwr寫數據文件,寫完之後ckpt更新控制文件和數據文件頭。此時若DBWR發現數據塊的log block還沒有被寫入日誌文件,則在dbwr寫塊之前通知lgwrlog buffer中的日誌寫入log文件。

註:總結一下,日誌切換必定觸發ckpt,但ckpt不一定會觸發lgwr,但是一定會觸發dbwr

4、其他的SCN

1)日誌文件頭中包含了Low scnNext scn,表示所給日誌文件包含有從Low scnNext scnredo record. (如何查看? REDO SCN)

註:當系統運行時,日誌文件的Next scn同樣為無窮大。而且需要註意:在恢復時定位到底使用哪個日誌文件的時候,並不是用數據文件中的low scn去框,也不是只要在日誌文件的low scn and next scn之間就利用該日誌文件。而是在數據文件頭中有RBA的記錄,RBA包含了日誌序號Sequence#、block number、slot number。 這樣可以直接定位到日誌文件(歸檔日誌文件)和具體的位置。

在確定了哪個數據文件必須redo後,oracle會比較change vector(向量)中的SCN和數據文件數據塊中的SCN,如果change vector的SCN小於數據塊的scn,則跳過此change vector,否則應用redo.

2)數據塊中的SCN

data block裏面的SCN是當block被更改的時候的SCN,而數據文件有那麽多block,自然不同的block有不同的SCNblock中存在block SCNITL中的commit SCNblock SCN又在塊頭和塊位都有,若不一致意味著block損壞。而ITL中的commit SCN則跟consistent gets and delay block cleanout有關。(Block SCN如何查看?)

3) v$database中的checkpoint_change#dbms_flashback.get_system_change_number不同。前者是作為數據庫的最後一次checkpoint是的SCN,而後者是系統的最新SCN,所以一般後者都會比前者大,而當剛做完checkpoint時候兩者會差不多。(Checkpoint的觸發機制?)

4)begin backup命令發出後,相關數據文件的checkpoint scn被凍結(以及狀態標誌被改變),其他一切照舊。例如:日誌切換時checkpoint count正常遞增/檢查點照常寫文件,自然文件中的數據塊內的各種scn也照常遞增。

5測試:

A.正常關閉,mount數據庫

SQL> col system_scn format 999999999999999999

SQL> col datafile_scn format 999999999999999999

SQL> col start_scn format 999999999999999999

SQL> col stop_scn format 999999999999999999

SQL> select a.checkpoint_change# system_scn, c.checkpoint_change# start_scn, scn, re rownum=1) c;

b.checkpoint_change# datafile_scn, decode(b.last_change#,NULL,‘null‘,b.last_change#) stop_scnp_scn

from v$database a,

(select checkpoint_change#, last_change# from v$datafile where rownum =1 ) b,

(select checkpoint_change# from v$datafile_header where rownum=1) c;

SYSTEM_SCN START_SCN DATAFILE_SCN STOP_SCN

------------------- ------------------- ------------------- ----------------------------------------

2696048203982 2696048203982 2696048203982 2696048203982

上述查詢結果表明:

結束SCN都是跟啟動SCN是一樣的,這樣,當數據庫open的時候就可以不用recover了。

把數據庫打開open

SQL> alter database open;

  Database altered.

SQL> select a.checkpoint_change# system_scn, c.checkpoint_change# start_scn,

2 b.checkpoint_change# datafile_scn, decode(b.last_change#,NULL,‘null‘,b.last_change#) stop_scn

3 from v$database a,

4 (select checkpoint_change#, last_change# from v$datafile where rownum =1 ) b,

5 (select checkpoint_change# from v$datafile_header where rownum=1) c;

SYSTEM_SCN START_SCN DATAFILE_SCN STOP_SCN

------------------- ------------------- ------------------- ----------------------------------------

2696048203983 2696048203983 2696048203983 null

系統檢查點scn增加了1

控制文件中的數據文件檢查點scn和數據文件的文件頭中的啟動scn也都各自增加了1

控制文件中的數據文件終止scn,變為NULL.

C.對系統觸發檢查點

SQL> alter system checkpoint;

  System altered.

SQL> select a.checkpoint_change# system_scn, c.checkpoint_change# start_scn,

2 b.checkpoint_change# datafile_scn, decode(b.last_change#,NULL,‘null‘,b.last_change#) stop_scn

3 from v$database a,

4 (select checkpoint_change#, last_change# from v$datafile where rownum =1 ) b,

5 (select checkpoint_change# from v$datafile_header where rownum=1) c;

SYSTEM_SCN START_SCN DATAFILE_SCN STOP_SCN

------------------- ------------------- ------------------- ----------------------------------------

2696048204212 2696048204212 2696048204212 null

系統檢查點scn發生變化,增加不止1,這與檢查點產生機制有關。

D異常關閉啟動!沒有將Start SCN同步給Stop SCN,造成不一致.需要Instance Recovery

SQL> shutdown abort

SQL> startup mount

Database mounted.

SQL> select a.checkpoint_change# system_scn, c.checkpoint_change# start_scn,

2 b.checkpoint_change# datafile_scn, decode(b.last_change#,NULL,‘null‘,b.last_change#) stop_scn

3 from v$database a,

4 (select checkpoint_change#, last_change# from v$datafile where rownum =1 ) b,

5 (select checkpoint_change# from v$datafile_header where rownum=1) c;

SYSTEM_SCN START_SCN DATAFILE_SCN STOP_SCN

------------------- ------------------- ------------------- ----------------------------------------

2696048204212 2696048204212 2696048204212 null

按理說在數據文件啟動之前End SCN的值不應為NULL,但這裏查出卻為NULL ,之前的理解是有誤的,Shutdown Abort, Stop SCN仍為NULL. (異常關閉後的Start Mount,在打開之前要做Instance Recovery)

SQL> alter database open;

Database altered.

Vi alert.log

alter database open

Mon Feb 1 14:27:05 2010

Beginning crash recovery of 1 threads

Mon Feb 1 14:27:05 2010

Started first pass scan

Mon Feb 1 14:27:05 2010

Completed first pass scan

61 redo blocks read, 30datablocks need recovery

Mon Feb 1 14:27:05 2010

Started recovery at

Thread 1: logseq 71, block 7466, scn 0.0

Recovery of Online Redo Log: Thread 1 Group 1 Seq 71 Reading mem 0

Mem# 0 errs 0: /opt/oracle/oradata/mydb/redo01.log

Mon Feb 1 14:27:05 2010

Completed redo application

Mon Feb 1 14:27:05 2010

Ended recovery at

Thread 1: logseq 71, block 7527, scn 627.3103729640

30 data blocks read, 30 data blocks written, 61 redo blocks read

Crash recovery completed successfully

完成在線日誌應用

SQL> select a.checkpoint_change# system_scn, c.checkpoint_change# start_scn, scn,

b.checkpoint_change# datafile_scn, decode(b.last_change#,NULL,‘null‘,b.last_change#) stop_scnp_scn

3 from v$database a,

4 (select checkpoint_change#, last_change# from v$datafile where rownum =1 ) b,

5 (select checkpoint_change# from v$datafile_header where rownum=1) c;

SYSTEM_SCN START_SCN DATAFILE_SCN STOP_SCN

------------------- ------------------- ------------------- ----------------------------------------

2696048224234 2696048224234 2696048224234 null

6小結

1、系統正常關閉:

  1)system checkpoint scn = datafile checkpoint scn = start scn,不需要介質恢復

  2)stop scn is not null = start SCN,不需要實例恢復

2、系統異常關閉:

  1)system checkpoint scn = datafile checkpoint scn = start scn,不需要介質恢復

  2)stop scn is null,需要實例恢復

3、舊數據文件

  會使得:system checkpoint scn = datafile checkpoint scn > start scnstop scn is null/ is not null

  1)system checkpoint scn = datafile checkpoint scn > start scn

需要介質恢復成system checkpoint scn = datafile checkpoint scn = start scn

2)stop scn is null,需要實例恢復,is not null不需要實例恢復

4備份控制文件

  會使得:system checkpoint scn = datafile checkpoint scn <= start scn(當數據文件為舊且和舊控制文件為同一版本的時候相等,如果數據文件是當前的數據文件則是小於)stop scn notnull/null

1)system checkpoint scn = datafile checkpoint scn <= start scn,需要使用using backup controlfile介質恢復成system scn = datafile scn = start scn = current log scn(當前日誌最大SCN)

2)為保證上一次恢復沒有用到log日誌不被使用,必須在恢復完成後用resetlogs打開數據庫

 

5、以noresetlogs方式重建控制文件

  在以這種方式重建控制文件時,控制文件中的datafile checkpoint scn來自於Online logs中的Current log頭,因此

  current log scn = system checkpoint scn = datafile scn >= start scn(如果數據文件為備份而來則會大於start SCN,如果是當前的則為相等於start SCN), stop scn not null/null

1)current log scn = system checkpoint scn = datafile checkpoint scn >= start scn,因此需要介質恢復成system checkpoint scn = datafile scn = start scn = redolog scn(當前日誌最大SCN) 

2)stopscn is not null不需要實例恢復

 

6、以resetlogs方式重建控制文件

  控制文件中datafile checkpoint scn來自各數據文件頭(start scn),而且system checkpoint scn會歸為0

  system checkpoint scn < datafile checkpoint scn = start scn,stop scn not null/null

1)system checkpoint scn < datafile checkpoint scn = start scn,需要使用using backup controlfile介質恢復成system checkpoint scn = datafile checkpoint scn = start scn(當前日誌最大SCN),stop scn not null

2) stopscn is not null不需要實例恢復,而且因為SCN已經為redolog scnlog已經不能使用,必須用resetlogs方式打開數據庫

7問題:

7.1數據庫啟動過程的兩個比較.

v$datafile_header.checkpoint_count VS 對應控制文件中的ckpt計數器(v$datafile.)在哪個視圖?

7.2 哪些情況下SCN會發生變化?這幾個SCN如何變化?

7.3 如何查看REDO SCN?

7.4 Block SCN如何查看?

7.5 Checkpoint的觸發機制?

下面這些操作將會觸發checkpoint事件:

1) 日誌切換,通過ALTER SYSTEM SWITCH LOGFILE。(之前的資料說這裏,發出的應是增量檢查點 ?是的,日誌切換只能產生增量檢查點)

2) DBA發出checkpoint命令,通過ALTER SYSTEM checkpoint。

3) 對數據文件進行熱備時,針對該數據文件的checkpoint也會進行,ALTER TABLESPACE TS_NAME BEGIN BACKUP/END BACKUP。

4) 當運行ALTER TABLESPACE/DATAFILE READ ONLY的時候。

5) SHUTDOWN命令發出時。

人生有三寶:終身運動,終身學習,終身反醒.吸收新知,提高效率,懂得相處,成就自己,也成就他人,創造最高價值。

Oracle SCN機制解析