oracle 檢查點,scn,事務關係

一、檢查點概述
大多數關係型數據庫都採用"在提交時並不強迫針對數據塊的修改完成"而是"提交時保證修改記錄(以重做日誌的形式)寫入日誌文件"的機制,來獲得性能的優勢。這句話的另外一種描述是:當用戶提交事務,寫數據文件是"異步"的,寫日誌文件是"同步"的。這就可能導致數據庫實例崩潰時,內存中的DB_Buffer 中的修改過的數據,可能沒有寫入到數據塊中。數據庫在重新打開時,需要進行恢復,來恢復DB Buffer 中的數據狀態,並確保已經提交的數據被寫入到數據塊中。檢查點是這個過程中的重要機制,通過它來確定,恢復時哪些重做日誌應該被掃描並應用於恢復
要了解這個檢查點,首先要知道checkpoint queue概念,檢查點發生後,觸發dbwr,CKPT獲取發生檢查點時對應的SCN,通知DBWr要寫到這個SCN爲止
dbwr 寫dirty buffer 是根據 buffer 在被首次修改的時候的時間的順序寫出,也就是 buffer被修改的時候會進入一個queue (checkpoint queue),dbwr 就根據queue從其中批量地寫到數據文件。 由於這裏有一個順序的關係,所以 dbwr的寫的進度就是可衡量的,寫到哪個buffer的時候該buffer的首次變化時候的scn就是當前所有數據文件block的最新scn,但是由於無法適時的將dbwr的進度記錄下來,所以oracle 選擇了一些策略。 其中就包括ckpt進程的檢查點和心跳。
檢查點發生以後,CKPT進程檢查checkpoint queue(也就是髒塊鏈表)是否過長,如果是,則觸發DBWr,將一部分髒塊寫入數據文件,從而縮短checkpoint queue。

checkpoint 發生時,一方面通知dbwr進行下一批寫操作,(dbwr 寫入的時候,一次寫的塊數是有一個批量寫的隱藏參數控制的。)另一方面,oracle 採用了一個心跳的概念,以3秒的頻率將dbwr 寫的進度反應到控制文件中,也就是把dbwr當前剛寫完的dirty buffer對應的scn 寫入數據文件頭和控制文件,這就是檢查點scn
這個3秒和增量檢查點不是一個概念,3秒只是在控制文件中,ckpt 進程去更新當前dbwr寫到哪裏了,這個對於ckpt 進程來說叫 heartbeat ,heartbeat是3秒一次,3秒可以看作不停的檢查並記錄檢查點執行情況(DBWR的寫進度)。
檢查點發生之後數據庫的數據文件、控制文件處於一致狀態的含義是不需要進行介質恢復,只表示數據文件頭一致,但是並不表示數據文件內容一致,因爲數據文件內容可能在沒有發生檢查點的其他情況下的dbwr寫數據文件,這樣數據文件內容就不一致,若掉電需要進行崩潰恢復。

二、SCN

SCN(System Chang Number)作爲oracle中的一個重要機制,在數據恢復、Data Guard、Streams複製、RAC節點間的同步等各個功能中起着重要作用。理解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
在正常的數據庫操作過程中,所有正處於聯機讀寫模式下的數據文件的終止scn都爲null.
5、在數據庫運行期間的scn值
在數據庫打開並運行之後,控制文件中的系統檢查點、控制文件中的數據文件檢查點scn和每個數據文件頭中的啓動scn都是相同的。控制文件中的每個數據文件的終止scn都爲null.
安全關閉數據庫的過程中,系統會執行一個檢查點動作,這時所有數據文件的終止scn都會設置成數據文件頭中的那個啓動scn的值。在數據庫重新啓動的時候,Oracle將文件頭中的那個啓動scn與數據庫文件檢查點scn進行比較,如果這兩個值相互匹配,oracle接下來還要比較數據文件頭中的啓動 scn和控制文件中數據文件的終止scn。如果這兩個值也一致,就意味着所有數據塊多已經提交,所有對數據庫的修改都沒有在關閉數據庫的過程中丟失,因此這次啓動數據庫的過程也不需要任何恢復操作,此時數據庫就可以打開了。當所有的數據庫都打開之後,存儲在控制文件中的數據文件終止scn的值再次被更改爲 null,這表示數據文件已經打開並能夠正常使用了。

三、事務過程

我們再看下oracle事務中的數據變化是如何寫入數據文件的:

1、 事務開始;

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

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

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

5、 當發生checkpoint,CKPT進程更新所有數據文件的文件頭中的信息,DBWr進程則負責將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都不會被更新

四、心跳

在Oracle中有一個事件叫Heartbeat,這個詞在很多地方被提及,並且有着不同的含義(比如RAC中),我們這裏要討論的是CKPT的Heartbeat機制。

Oracle通過CKPT進程每3秒將Heartbeat寫入控制文件,以減少故障時的恢復時間(這個我們後面再詳細闡述)。

我們可以通過如下方法驗證這個過程。

1.首先在系統級啓用10046時間跟蹤

並重新啓動數據庫使之生效

[oracle@jumper oracle]$ sqlplus "/ as sysdba"
SQL*Plus: Release 9.2.0.4.0 - Production on Thu Jan 19 09:24:04 2006
Copyright (c) 1982, 2002, Oracle Corporation. All rights reserved.
Connected to:Oracle9i Enterprise Edition Release 9.2.0.4.0 - ProductionWith the Partitioning optionJServer Release 9.2.0.4.0 - Production
SQL> alter system set event='10046 trace name context forever,level 12' scope=spfile;
System altered.
SQL> shutdown immediate;Database closed.Database dismounted.ORACLE instance shut down.
SQL> startupORACLE instance started.
Total System Global Area 114365800 bytesFixed Size                   451944 bytesVariable Size              50331648 bytesDatabase Buffers           62914560 bytesRedo Buffers                 667648 bytesDatabase mounted.Database opened.SQL> exitDisconnected from Oracle9i Enterprise Edition Release 9.2.0.4.0 -
ProductionWith the Partitioning optionJServer Release 9.2.0.4.0 - Production
2.檢查bdump目錄下生成的跟蹤文件

目錄在$ORACLE_HOME/admin/$ORACLE_SID/bdump目錄下,每個後臺進程都會生成一個跟蹤文件。

[oracle@jumper bdump]$ ls20050424_alert_conner.log conner_arc0_2569.trc
conner_dbw0_2559.trc conner_reco_2567.trcalert_conner.log           conner_arc1_2571.trc
conner_lgwr_2561.trc conner_smon_2565.trca.sql                      conner_ckpt_2563.trc
conner_pmon_2557.trc
3.檢查CKPT進程的跟蹤文件

我們可以很容易的發現CKPT進程每3秒都對控制文件進行一次寫入

[oracle@jumper bdump]$ tail -f conner_ckpt_2563.trc WAIT #0: nam='rdbms ipc message' ela= 2994710 p1=300 p2=0 p3=0WAIT #0: nam='control file parallel write' ela= 2442 p1=3 p2=3 p3=3WAIT #0: nam='rdbms ipc message' ela= 2995171 p1=300 p2=0 p3=0WAIT #0: nam='control file parallel write' ela= 2586 p1=3 p2=3 p3=3WAIT #0: nam='rdbms ipc message' ela= 2994962 p1=300 p2=0 p3=0WAIT #0: nam='control file parallel write' ela= 2582 p1=3 p2=3 p3=3WAIT #0: nam='rdbms ipc message' ela= 2995020 p1=300 p2=0 p3=0WAIT #0: nam='control file parallel write' ela= 2455 p1=3 p2=3 p3=3WAIT #0: nam='rdbms ipc message' ela= 2995188 p1=300 p2=0 p3=0WAIT #0: nam='control file parallel write' ela= 2412 p1=3 p2=3 p3=3WAIT #0: nam='rdbms ipc message' ela= 2995187 p1=300 p2=0 p3=0WAIT #0: nam='control file parallel write' ela= 2463 p1=3 p2=3 p3=3WAIT #0: nam='rdbms ipc message' ela= 2995095 p1=300 p2=0 p3=0WAIT #0: nam='control file parallel write' ela= 2448 p1=3 p2=3 p3=3
4.檢查控制文件的變更

通過2次dump控制文件,比較其trace文件輸出可以比較得到不同之處,我們發現,Oracle僅僅更新了Heartbeat這個數值。

[oracle@jumper udump]$ sqlplus "/ as sysdba"
SQL*Plus: Release 9.2.0.4.0 - Production on Wed Jan 18 22:44:10 2006
Copyright (c) 1982, 2002, Oracle Corporation. All rights reserved.
Connected to:Oracle9i Enterprise Edition Release 9.2.0.4.0 - ProductionWith the Partitioning optionJServer Release 9.2.0.4.0 - Production
SQL> alter session set events 'immediate trace name CONTROLF level 10';
Session altered.
SQL> exitDisconnected from Oracle9i Enterprise Edition Release 9.2.0.4.0 - ProductionWith the Partitioning optionJServer Release 9.2.0.4.0 - Production[oracle@jumper udump]$ sqlplus "/ as sysdba"
SQL*Plus: Release 9.2.0.4.0 - Production on Wed Jan 18 22:44:18 2006
Copyright (c) 1982, 2002, Oracle Corporation. All rights reserved.
Connected to:Oracle9i Enterprise Edition Release 9.2.0.4.0 - ProductionWith the Partitioning optionJServer Release 9.2.0.4.0 - Production
SQL> alter session set events 'immediate trace name CONTROLF level 10' ;
Session altered.
SQL> exitDisconnected from Oracle9i Enterprise Edition Release 9.2.0.4.0 - ProductionWith the Partitioning optionJServer Release 9.2.0.4.0 - Production
[oracle@jumper udump]$ lsconner_ora_21896.trc conner_ora_21898.trc[oracle@jumper udump]$ diff conner_ora_21896.trc conner_ora_21898.trc 1c1< /opt/oracle/admin/conner/udump/conner_ora_21896.trc---> /opt/oracle/admin/conner/udump/conner_ora_21898.trc14c14< Unix process pid: 21896, image: [email protected] (TNS V1-V3)---> Unix process pid: 21898, image: [email protected] (TNS V1-V3)16c16< *** SESSION ID9.813) 2006-01-18 22:44:14.314---> *** SESSION ID9.815) 2006-01-18 22:44:21.569
63c63< heartbeat: 579991793 mount id: 3191936000---> heartbeat: 579991796 mount id: 3191936000 [oracle@jumper udump]$


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章