oracle checkpoint

什麼是checkpoint

在數據庫系統中,寫日誌和寫數據文件是數據庫中IO消耗最大的兩種操作,在這兩種操作中寫數據文件屬於分散寫,寫日誌文件是順序寫,因此爲了保證數據庫的性能,通常數據庫都是保證在提交(commit)完成之前要先保證日誌都被寫入到日誌文件中,而髒數據塊着保存在數據緩存(buffer cache)中再不定期的分批寫入到數據文件中。也就是說日誌寫入和提交操作是同步的,而數據寫入和提交操作是不同步的。這樣就存在一個問題,當一個數據庫崩潰的時候並不能保證緩存裏面的髒數據全部寫入到數據文件中,這樣在實例啓動的時候就要使用日誌文件進行恢復操作,將數據庫恢復到崩潰之前的狀態,保證數據的一致性。檢查點是這個過程中的重要機制,通過它來確定,恢復時哪些重做日誌應該被掃描並應用於恢復。

一般所說的checkpoint是一個數據庫事件(event),checkpoint事件由checkpoint進程(LGWR/CKPT進程)發出,當checkpoint事件發生時DBWn會將髒塊寫入到磁盤中,同時數據文件和控制文件的文件頭也會被更新以記錄checkpoint信息。


checkpoint的作用

checkpoint主要2個作用:

  1. 保證數據庫的一致性,這是指將髒數據寫入到硬盤,保證內存和硬盤上的數據是一樣的;

  2. 縮短實例恢復的時間,實例恢復要把實例異常關閉前沒有寫出到硬盤的髒數據通過日誌進行恢復。如果髒塊過多,實例恢復的時間也會很長,檢查點的發生可以減少髒塊的數量,從而提高實例恢復的時間。

通俗的說checkpoint就像word的自動保存一樣。



checkpoint相關概念術語


RBA(Redo Byte Address), Low RBA(LRBA), High RBA(HRBA)

RBA就是重做日誌塊(redo log block)的地址,相當與數據文件中的ROWID,通過這個地址來定位重做日誌塊。RBA由三個部分組成:

  1. 日誌文件序列號(4字節)

  2. 日誌文件塊編號(4字節)

  3. 重做日誌記錄在日誌塊中的起始偏移字節數(2字節)

通常使用RBA的形式有:

  • LRBA

  • 數據緩存(buffer cache)中一個髒塊第一次被更新的時候產生的重做日誌記錄在重做日誌文件中所對應的位置就稱爲LRBA。

  • HRBA

  • 數據緩存(buffer cache)中一個髒塊最近一次被更新的時候產生的重做日誌記錄在重做日誌文件中所對應的位置就稱爲HRBA。

  • checkpoint RBA

  • 當一個checkpoint事件發生的時候,checkpoint進程會記錄下當時所寫的重做日誌塊的地址即RBA,此時記錄的RBA被稱爲checkpoint RBA。從上一個checkpoint RBA到當前的checkpoint RBA之間的日誌所保護的buffer cache中的髒塊接下來將會被寫入到數據文件當中去。

Buffer checkpoint Queues (BCQ)

Oracle將所有在數據緩存中被修改的髒塊按照LRBA順序的組成一個checkpoint隊列,這個隊列主要記錄了buffer cache第一次發生變化的時間順序,然後有DBWn進程根據checkpoint隊列順序將髒塊寫入到數據文件中,這樣保證了先發生變更的buffer能先被寫入到數據文件中。BCQ的引入是爲了支持增量checkpoint的。

Active checkpoint Queue (ACQ)

ACQ中包含了所有活動的checkpoint請求。每次有新checkpoint請求是都會在ACQ中增加一條記錄,ACQ記錄中包含了相應的checkpoint RBA。checkpoint完成以後相應的記錄將被移出隊列。



完全檢查點工作過程

一個checkpoint操作可以分成三個不同的階段:

  • 第一階段,checkpoint進程開始一個checkpoint事件,並記錄下checkpoint RBA,這個通常是當前的RBA。

  • 第二階段,checkpoint進程通知DBWn進程將所有checkpoint RBA之前的buffer cache裏面的髒塊寫入磁盤。

  • 確定髒塊都被寫入磁盤以後進入到第三階段,checkpoint進程將checkpoint信息(SCN)寫入/更新數據文件和控制文件中。

更新SCN的操作由CKPT進程完成,在Oracle 8.0之後CKPT進程默認是被啓用的,如果CKPT進程沒有啓用的話那相應的操作將由LGWR進程完成。


什麼時候發生normal checkpoint

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

  • 日誌切換,通過ALTER SYSTEM SWITCH LOGFILE。

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

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

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

  • SHUTDOWN命令發出時。

特別注意:

  1. 日誌切換會導致checkpoint事件發生,但是checkpoint發生卻不會導致日誌切換。

  2. 日誌切換觸發的是normal checkpoint,而不是大家所說的增量checkpoint,只不過log switch checkpoint的優先級非常低,當一個log switch checkpoint發生的時候它並不會立即的通知DBWn進程去寫數據文件,但是當有其它原因導致checkpoint或者是寫入數據文件的RBA超過log switch checkpoint的checkpoint RBA的時候,這次的log switch checkpoint將會被標記成完成狀態,同時更新控制文件和數據文件頭。我們隨後可以做個實驗驗證這個說法。



發生增量checkpoint的先決條件

  • 恢復需求設定 (FAST_START_IO_TARGET/FAST_START_MTTR_TARGET)

  • LOG_checkpoint_INTERVAL參數值

  • LOG_checkpoint_TIMEOUT參數值

  • 最小的日誌文件大小

  • buffer cache中的髒塊的數量



增量checkpoint相關參數設置

  • log_checkpoint_interval

  • 設定兩次checkpoint之間重做日誌塊(重做日誌塊和系統數據塊是一樣的)數,當重做日誌塊數量達到設定值的時候將觸發checkpoint。

  • log_checkpoint_timeout

  • 設定兩次checkpoint之間的間隔時間,當超時值達到時增量checkpoint將被觸發。Oracle建議不用這個參數來控制,因爲事務(transaction)大小不是按時間等量分佈的。將此值設置成0時將禁用此項設置。

  • fast_start_io_target

  • 因爲log_checkpoint_interval主要看的時候重做日誌塊的數量,並不能反應buffer cache中髒數據塊的修改,因此Oracle又引入了這個參數來實現當髒數據塊達到一定數量的時候觸發checkpoint,不過此參數實際上控制的是恢復時所需IO的數量。

  • fast_start_mttr_target

    • 此參數是在9i中引入用來代替前面的三個參數的,它定義了數據塊崩潰後所需要的實例恢復的時間,Oracle在實際上內在的解釋成兩個參數:fast_start_io_target和log_checkpoint_interval.如果這兩個參數沒有顯式的指定,計算值將生效.。

    • fast_start_mttr_target可以設定的最大值是3600,即一個小時。它的最小值沒有設限,但是並不是說可以設置一個任意小的值,這個值會受最小dirty buffer(最小爲1000)的限制,同時還會受初始化時間以及文件打開時間的限制。

    • 在設置此參數的時候要綜合考慮系統的IO,容量以及CPU等信息,要在系統性能和故障恢復時間之間做好平衡。

    • 將此參數設置成0時將禁用 fast-start checkpointing,這樣能見效系統負載但同時會增加系統的恢復時間。

    • 如果fast_start_io_target or log_checkpoint_interval被指定,他們會自動覆蓋由fast_start_mttr_target參數計算出來的值。

在10g中,數據庫能根據各種系統參數的設置值來自動調整檢查點的執行頻率,以獲得最好的恢復時間以及系統的正常運行影響最小。通過自動checkpoint調整,Orach能在系統低IO操作的時候將髒塊寫入到數據文件中,因此即時DBA沒有設置checkpoint相關的參數值或是設置了一個不合理的值的時候系統還是能獲得一個很合理的系統恢復時間。

10g中的增量checkpoint更能體現它持續活動的特點,在10g中,增量checkpoint不是在某一個特定的條件下觸發,而是由數據庫根據系統參數設置自動觸發。




查看系統的checkpoint動作


我們可以通過將LOG_checkpointS_TO_ALERT設置成TRUE來打開checkpoint的trace,這樣就可以跟蹤checkpoint的操作了。

ALTER SYSTEM SET LOG_checkpointS_TO_ALERT=TRUE;

這設置以後系統的checkpoint將會被記錄alert_$SID.log文件中。

在V$DATAFILE_HEADER裏面也保存了發生完全checkpoint的時候一些相關信息,包括checkpoint發生時間、對應SCN已經checkpoint的次數。





要了解這個檢查點,首先要知道checkpoint queu概念,檢查點發生後,觸發dbwn,CKPT獲取發生檢查點時對應的SCN,通知DBWn要寫到這個SCN爲止, 
dbwr 寫dirty buffer 是根據 buffer 在被首次 modify的時候的時間的順序寫出,也就是 buffer被modify 的時候會進入一個queue (checkpoint queue),dbwr 就根據queue從其中批量地寫到數據文件。 由於這裏有一個順序的關係,所以 dbwr的寫的進度就是可衡量的,寫到哪個buffer的時候該buffer的首次變化時候的scn就是當前所有數據文件block的最新scn,但是由於無法適時的將dbwr的進度記錄下來,所以oracle 選擇了一些策略。 其中就包括ckpt進程的檢查點和心跳。

檢查點發生以後,CKPT進程檢查checkpoint queue(也就是髒塊鏈表)是否過長,如果是,則觸發DBWn,將一部分髒塊寫入數據文件,從而縮短checkpoint queue。checkpoint 發生時,一方面通知dbwr進行下一批寫操作,(dbwr 寫入的時候,一次寫的塊數是有一個批量寫的隱藏參數控制的。)另一方面,oracle 採用了一個心跳的概念,以3秒的頻率將dbwr 寫的進度反應到控制文件中,也就是把dbwr當前剛寫完的dirty buffer對應的scn 寫入數據文件頭和控制文件,這就是檢查點scn。
這個3秒和增量檢查點不是一個概念,3秒只是在控制文件中,ckpt 進程去更新當前 dbwr寫到哪裏了,這個對於 ckpt 進程來說叫 heartbeat ,heartbeat是3秒一次,3秒可以看作不停的檢查並記錄檢查點執行情況(DBWR的寫進度)。

檢查點發生之後數據庫的數據文件、控制文件處於一致狀態的含義是不需要進行 介質恢復,只表示數據文件頭一致,但是並不表示數據文件內容一致,因爲數據文件內容可能在沒有發生檢查點的其他情況下的dbwr寫數據文件,這樣數據文件內容就不一致,若掉電需要進行崩潰恢復。


Commit成功後,數據還會丟失嗎?
對於Oracle來說,用戶所做的DML操作一旦被提交,則先是在database buffer cache 中進行修改,同時在修改之前會將數據的前鏡像保存在回滾段中,然後將修改之前和修改之後的數據都寫入到redo log buffer中,當接收到commit命令之後,則redo log buffer開始寫redo log file ,並且記錄此時的scn,當redo log file 寫完了之後,表示這次事務提交操作已經確認被數據庫記錄了,只有當redo log file 寫成功了,纔會給用戶 Commit completed 的成功字樣。而對於Database buffer cache中的dirty buffer則會等待觸發DBWn才寫入,但是如果此時斷電,則數據已經被記錄到了redo log file中,系統在重新啓動的時候,會自動進行嵌滾和回滾來保證數據的一致。所以,只要是commit成功的了,數據不會丟失!


數據庫發生一次DBWn,是否將所有buffer cache 中的dirty buffer 都寫入,還是先將髒隊列中的數據寫入? 

這話看起來有道理,但實際上,dbwr在寫的時候又不斷地在產生dirty buffer ,所以說檢查點發生的時候是期望把該時間點之前的所有髒緩衝區寫入數據文件。
所有的buffer,不在LRU list上就在dirty list上, dbwr寫入的時候,一次寫的塊數是有一個批量寫的隱藏參數控制的。
所以說要是 dbwr將 dirty list也好, lru list上的也好,要實現全部寫入,都是一個現實系統中很難存在的現象。dirty 總是在不斷的產生,dbwr總是在不斷地寫,增量檢查點發生的時候也並不意味着一定要更新數據文件頭,檢查點開始的時候只表示該次檢查點結束的時候要更新數據文件頭的話數據文件頭具有該時間點的一致性。




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