[zt]Oracle檢查點ckpt (checkpoint)

tolywang發表於2008-12-31


由於Oracle中LGWR和DBWR工作的不一致,Oracle引入了檢查點的概念,用於同步資料庫,保證資料庫的一致性。在Oracle裡面,檢查點分為兩種:完全檢查點和增量檢查點。下面我們分別介紹這兩種檢查點的作用:


1、 完全檢查點

在Oracle8i之前,資料庫的發生的檢查點都是完全檢查點,完全檢查點會將資料緩衝區裡面所有的髒資料塊寫入相應的資料檔案中,並且同步資料檔案頭和控制檔案,保證資料庫的一致。完全檢查點在8i之後只有在下列兩種情況下才會發生:

(1、)DBA手工執行alter system checkpoint的命令;

(2、)資料庫正常shutdown(immediate,transcational,normal)。

由於完全檢查點會將所有的髒資料庫塊寫入,巨大的IO往往會影響到資料庫的效能。因此Oracle從8i開始引入了增量檢查點的概念。


2、 增量檢查點
Oracle從8i開始引入了檢查點佇列這麼一種概念,用於記錄資料庫裡面當前所有的髒資料塊的資訊,DBWR 根據這個佇列而將髒資料塊寫入到資料檔案中。檢查點佇列按時間先後記錄著資料庫裡面髒資料塊的資訊,裡面的條目包含RBA(Redo Block Address,重做日誌裡面用於標識檢查點期間資料塊在重做日誌裡面第一次發生更改的編號)和資料塊的資料檔案號和塊號。在檢查點期間不論資料塊更改幾次,它在檢查點佇列裡面的位置始終保持不變,檢查點佇列也只會記錄它最早的RBA,從而保證最早更改的資料塊能夠儘快寫入。當DBWR將檢查點佇列裡面的髒資料塊寫入到資料檔案後,檢查點的位置也要相應地往後移,CKPT每三秒會在控制檔案中記錄檢查點的位置,以表示Instance Recovery時開始恢復的日誌條目,這個概念稱為檢查點的“心跳”(heartbeat)。檢查點位置發生變更後,Oracle裡面透過4個引數用於控制檢查點位置和最後的重做日誌條目之間的距離。在這裡面需要指出的是,多數人會將這4個引數看作控制增量檢查點發生的時間。事實上這是錯誤的,這4個引數是用於控制檢查點佇列裡面的條目數量,而不是控制檢查點的發生。

(1、)fast_start_io_target
該引數用於表示資料庫發生Instance Recovery的時候需要產生的IO總數,它透過v$filestat的AVGIOTIM來估算的。比如我們一個資料庫在發生Instance Crash後需要在10分鐘內恢復完畢,假定OS的IO每秒為500個,那麼這個資料庫發生Instance Recovery的時候大概將產生500*10*60=30,000次IO,也就是我們將可以把fast_start_io_target設定為 30000。

(2、)fast_start_mttr_target
我們從上面可以看到fast_start_io_target來估算檢查點位置比較麻煩。Oracle為了簡化這個概念,從9i開始引入了 fast_start_mttr_target這麼一個引數,用於表示資料庫發生Instance Recovery的時間,以秒為單位。這個引數我們從字面上也比較好理解,其中的mttr是mean time to recovery的簡寫,如上例中的情況我們可以將fast_start_mttr_target設定為600。當設定了 fast_start_mttr_target後,fast_start_io_target這個引數將不再生效,從9i後 fast_start_io_target這個引數被Oracle廢除了。

(3、)log_checkpoint_timeout
該引數用於表示檢查點位置和重做日誌檔案末尾之間的時間間隔,以秒為單位,預設情況下是1800秒。

(4、)log_checkpoint_interval
該引數是表示檢查點位置和重做日誌末尾的重做日誌塊的數量,以OS塊表示。

(5、)90% OF SMALLEST REDO LOG
除了以上4個初始化引數外,Oracle內部事實上還將重做日誌檔案末尾前面90%的位置設為檢查點位置。在每個重做日誌中,這麼幾個引數指定的位置可能不盡相同,Oracle將離日誌檔案末尾最近的那個位置確認為檢查點位置。

oracle 9i instance recovery
1. 增量檢查點
在checkpoint queue的基礎上實現了增量檢查點,每3秒發生一次checkpoint heartbeat,記錄dbwr上次寫成功的最大RBA(redo block address)。這樣的話做instance recovery的時候就從這個rba開始,而不是從上次checkpoint scn開始,大大節省了恢復時間。
 
2. twice scan of redo log
在應用redo之前,redo將會被操作兩次,第一次去掃描哪些redo record需要被應用,因為9i在redo裡新增了dbwr寫資料塊的資訊,所以dbwr發生前的日誌將不會被應用。第二步就是選出需要被應用的日誌然後開始rollforward。
 
3. rollforward
在做instance recovery時必須先定位到redo log 然後應用所有日誌到datafile,這時候包括了committed和uncommitted的資料。當做完rollward,資料庫就可以open了。
 
4. rollback
因 為rollforward產生了uncommitted資料,所以必須回滾這些資料。這將由smon和on-demand rollback來實現。smon將會掃描undo segment header去標誌所有活動事務為dead,然後會逐漸去回滾這些事務。另外on-demand rollback提供了前臺程式進行rollback,當前臺程式企圖獲得被dead事務佔用row lock,這時候前臺程式將會去undo segment取得before image去回滾這個塊,至於其他被這個dead事務lock的塊就等待smon去回滾。
 
另外,如果 在資料庫開啟的過程中process crash導致transaction dead,resource不能被釋放的情況,這時候如果另一個程式需要這些resource,那麼這個程式將會等待直到pmon清理dead process釋放出resource。

如果資料庫Crash,重新啟動,很久遠以前的未提交事務並不在Redo的恢復序列中。
但是未提交事務一定在回滾段事務表上存在,並且State=10,為活動事務。這就夠了。

資料庫啟動之後,這些事務會被SMON逐個標記為Dead(不可能再活過來了),然後由SMON慢慢去回滾這些事務;也存在另外一種情況,後來的程式會去讀這些未提交資料,發現Dead事務未提交,則主動進行回滾。

1. 一個資料塊發生更新,必然寫回滾
2. 回滾段的block變化也記錄在redo中

一份未提交的資料必定在回滾中有相應的前映象,任何正常的恢復都一定會把這些變化重新構建出來。


想像一下

1. update事務1更新了block 1
2. 回滾段1記錄了block1的前映象
3. checkpoint
4. update事務2更新了block2
5. 回滾段2記錄了block2的前映象
6. instance crash

現在重啟資料庫

1. 根據redo重新構建block2
2. 根據redo重新構建回滾段2
3. database open
4. SMON用回滾段2的資料回滾block2,SMON用回滾段1的資料回滾block1

最後一步也可能是
在另外一個select檢索到block1或者block2的時候,發現這兩個block的資料都是未提交的,此時再回滾block1和block2。

所以,只要有相應的回滾資料存在,無論什麼時候oracle都可以找到一致的資料,oracle只需要知道這個事務是提交了的還是沒提交了的,而這點在block header ITL中有記錄。

 http://spaces.msn.com/roujiaweize/blog/cns!9745F14B4AEB3B72!328.entry

對SCN和CKPT的一點理解

scn (system change number,系統改變號),它提供 oracle 的內部時鐘機制,定義資料庫在某個確切時刻提交的版本,其作用是維護資料庫的資料的一致性。


ckpt (checkpoint,檢查點),它是一個資料庫事件,它將已修改的資料從快取記憶體重新整理寫入磁碟,並更新控制檔案和資料檔案。在一個檢查點之後,重做日誌檔案中的重做記錄對於崩潰/例項恢復不再有用。


控制檔案為每個資料檔案儲存有一個:checkpoint scn, stop scn,只有資料檔案中有 stop scn
select name,checkpoint_change#,last_change# from v$datafile;


系統檢查點 scn (這個看別人寫的,不懂)
select checkpoint_change# from v$database;
當一個檢查點動作完成後,oracle 就把系統檢查點的 scn 儲存到控制檔案中。


資料檔案頭:資料庫 checkpoint scn
select name,checkpoint_change# from v$datafile_header;(這個是資料庫正常開啟時從控制檔案中查的,因為資料庫正常開啟時這兩個相等,資料檔案頭真正的 scn,oracle 自己讀檔案頭)


控制檔案為每個 redo 執行緒儲存有一個:checkpoint scn
select thread#,checkpoint_change# from v$thread;


當一個檢查點動作完成後,oracle 更新控制檔案中的這些 checkpoint scn (控制檔案中一個,所有資料檔案頭在控制檔案中的儲存,redo 在控制檔案中的資訊),以及資料檔案頭中的 checkpoint scn。所以可以理解,上面這些值都是從控制檔案中取出來的。


當資料庫用 normal 或者 immediate 選項關閉時,執行檢查點,更新控制檔案中資料檔案的 stop scn,等於資料檔案頭中的 checkpoint scn。


下次啟動資料庫時,oracle 要進行兩次檢查。第一次看資料檔案頭中的 checkpoint scn 與控制檔案中資料檔案的 checkpoint scn。如果相等,進行第二次檢查,檢查資料檔案頭中的 checkpoint scn 與控制檔案中資料檔案的 stop scn。如果相等,不需要對這個檔案恢復。每個資料檔案都做這樣的檢查,然後開啟資料庫,將每個 stop scn 重新置為無窮大。


如果用 abort 關閉資料庫,則不執行檢查點處理,控制檔案中資料檔案的 stop scn 仍為無窮大。


下次啟動時做兩次檢查。如第一次相等,再比較第二個。這時,資料檔案頭中的 checkpoint scn 一定是小於控制檔案中資料檔案的 stop scn 的,需要進行崩潰/例項恢復,進行前滾和回滾。


如果用備份代替了資料檔案再啟動資料庫,這時做第一次檢查時,資料檔案頭中的 checkpoint scn 一定小於控制檔案中資料檔案的 checkpoint scn;或者用備份的控制檔案代替了控制檔案再啟動資料庫,這時資料檔案頭中的 checkpoint scn 一定大於控制檔案中資料檔案的 checkpoint scn。只要這兩個不相等,就需要介質恢復。


還有一種情況,如果控制檔案和資料檔案都是備份的,而這兩個 checkpoint scn 正好相等,第一次比較透過,那麼再看第二次比較了。其實這個時候在第一次比較之前,會先比較控制檔案中 redo 執行緒的 checkpoint scn 的和 online log 的 scn,如果相等,繼續,如果不相等(小於),提示控制檔案是舊的需要介質恢復。

 

本文件來自於(http://blog.itpub.net/post/94/63495)

 

來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/35489/viewspace-524784/,如需轉載,請註明出處,否則將追究法律責任。

相關文章