關於log file switch and checkpoint機制

darren__chan發表於2021-10-08

轉自同事周乙的研究總結,記錄一下!


關於 ckpt 的機制

 

何時發生 check point?

1.       每次 redo file switch

2.       當達到引數 LOG_CHECKPOINT_TIMEOUT 設定值。

3.       當有( LOG_CHECKPOINT_INTERVAL* IO OS 塊大小)的位元組大小寫入當前重做日誌檔案時。

4.       當執行 alter system switch logfile 時。

5.       當執行 alter system checkpoint 時。

 

發生 check point 時, ckpt 程式會將檢查點資訊刷入控制檔案,更新資料檔案 header ,如下圖所示:

檢查點又分為增量檢查點以及全量檢查點。

全量檢查點: 所有 dirty blocks 刷回磁碟後,再進行更新控制檔案以及資料檔案 header 更新。

增量檢查點:目的是避免在聯機重做日誌切換時寫入大量塊。 DBWn 至少每三秒檢查一次以確定它是否有工作要做。 DBWn 寫入髒緩衝區時, CKPT 會將檢查點位置寫入控制檔案,而不是寫入資料檔案 header

以上內容來自: Primary Note: Overview of Database Checkpoints (Doc ID 1490838.1)

 

Oracle 8i 後,全量檢查點只會發生在 shutdown database 與手工發起 alter system checkpoint 的時候。

增量檢查點的工作涉及到 ckpt lgwr dbwr 三者的聯動,在這裡我們假設 os IO 沒有瓶頸。

 

Oracle 內建了一條 Checkpoint Queue ,主要用於兩個方面:

1.       記錄哪一些 dirty block 需要 dbwr 刷回磁碟。

2.       用於定位當 instance crash 後需要從 redo log 開始恢復的位置。

 

Checkpoint Queue 是一個髒緩衝區列表,按它們第一次髒的時間順序排列。這條 Queue 也是 dbwr 程式用於識別哪些塊需要被刷回磁碟。同時這條 Queue 也用於與 redo file 進行匹配,在這條 Queue 上的髒快在進行 crash recovery 的時候是需要被恢復的。

ckpt 程式會將 Checkpoint  Queue 中第一個記錄的 RBA 記錄到 control file 中,以標記 checkpoint position ckpt 程式每三秒就會刷一次 Checkpoint Queue 資訊至 control file ,這個動作就是 incremental checkpoint

ckpt 程式也會在 redo 切換後重新整理 checkpoint position 到資料檔案 header ,但由於不是 full checkpoint ,所以不會重新整理所有資料檔案 header ,而是基於 Checkpoint Queue 計算判斷重新整理哪一個資料檔案 header

dbwr 程式會基於 Checkpoint Queue 重新整理 dirty blocks ,一旦 dbwr 重新整理完成,它會將這些將這些重新整理完的 blocks 資訊從 Checkpoint Queue 移除並將重新整理過的塊的資訊刷入 redo( 用於加速 crash recover) ,這時候 ckpt 程式又會重新整理 Checkpoint Queue 資訊到 control file ,如此往復。

有如下 3 個引數可以顯式的控制 checkpoint queue 的長度

LOG_CHECKPOINT_TIMEOUT :指定(以秒為單位)自上次寫入 redo incremental checkpoint 以來經過的時間量。 此引數還表示 dirty blocks (在 buffer 中)超過整數秒。

LOG_CHECKPOINT_INTERVAL :根據 incremental checkpoint 和寫入 redo 的最後一個塊之間可以存在的 redo log file blocks 的數量來指定 checkpoint 的頻率。 這個數字是指物理作業系統塊,而不是資料庫塊。同時這個引數在非 0 時才有意義。

FAST_START_MTTR_TARGET :基於需要恢復的 redo 數量進行恢復,從而控制 checkpoint Queue 的長度,使用時需要移除 LOG_CHECKPOINT_INTERVAL, LOG_CHECKPOINT_TIMEOUT 的設定,因為會被上述兩個引數覆蓋。

另外還有一個計算 checkpoint position 的內建考量點, 90% 最小 redo 。如下圖所示:

      這個區間則是 90% 最小 redo

3 個引數與 90% 最小 redo 的計算依據都是在 incremental checkpoint end of the redo 之間,而 checkpoint queue 則是就是 incremental checkpoint end of the redo 之間的長度。由於除非資料庫關閉,否則 the end of redo 是一直在變化的,所以 incremental checkpoint 的更新速度就會在上述三個引數的控制下加速 / 減緩,從而控制 checkpoint queue 的長度。到這裡應該注意到,調整這三個引數的本質,就是控制 dbwr 程式刷 dirty blocks 的速度。

假設 FAST_START_MTTR_TARGET A 90% 最小 redo B LOG_CHECKPOINT_TIMEOUT C LOG_CHECKPOINT_INTERVAL D

4 者控制 checkpoint queue 長度如下圖所示:

有了上述這些基礎機制,我們開始討論我們的 case

Ckpt 程式只會告知 dbwr 程式需要開始工作,但是不會強制 dbwr 程式去刷塊,最終一次重新整理多少,是由 dbwr 程式決定,而 dbwr 程式刷多少,則是由上述 4 個控制因素以及 end of the redo 來決定的。 Ckpt 程式只會強制自己將 checkpoint redo RBA 寫入 control file 。如果此時 checkpoint queue 中記錄的 dirty blocks 大於上述 4 個控制因素決定的 queue 長度, dbwr 才會全力去重新整理 dirty blocks ,否則它將會按照自己的節奏慢慢的去刷 dirty blocks lazy write )。

Redo file active inactive (紅色進度條為需要刷回磁碟的 dirty blocks ,藍色為還未刷回磁碟的 dirty blocks 也就是 check point queue 的長度):

1.       此時 current redo log 1

2.       當前 checkpoint

3.       大量 redo 產生:

4.       Checkpoint queue 的變化:

1-4 描述了在單一 redo checkpoint queue 以及 checkpoint queue 的變化

 

5.       checkpoint 橫跨兩份 redo 時:

Checkpoint 不斷移動

所以 inactive redo 少於 2 組,是因為 checkpoint queue 的長度決定的。而如果增長 / 縮短 checkpoint queue 則是由 FAST_START_MTTR_TARGET 90% 最小 redo LOG_CHECKPOINT_TIMEOUT LOG_CHECKPOINT_INTERVAL 來共同決定的,在 oracle 10G 以後,更多情況下,是由引數 FAST_START_MTTR_TARGET 來進行控制的,如非必要,不會單獨去調整 LOG_CHECKPOINT_TIMEOUT LOG_CHECKPOINT_INTERVAL 90% 最小 redo 是硬性條件,無法調整。)。

所以在 os 沒有 io 瓶頸, ckpt lgwr dbwr 都工作正常的情況下, inactive redo log 少於 2 組,也是正常現象。

 

至此 active/inactive redo 問題解釋完成。


既然 inactive redolog 是正常行為, 那麼如何跟不正常行為區分開呢?


正常的 inactive  redo 數量是 db 的正常工作的機制保證的,而不正常的 inactive redo 數量是因為 db 異常 /io 異常等等因素造成的。

     如果我們能夠知道全天最大每秒日誌量, redo 大小,日誌組數,通過這三者可以大概計算出如何設定 mrrt 可以保證至少有多少個 inactive redo ,如果低於這個值的 inactive redo 數量,則可視為不正常。

     我們為另外一些客戶做過類似的控制,大致的計算公式為:

     我們取全天日誌產生量最大的時間段(大概 10 分鐘)的日誌平均每秒的產生量為 N

     日誌組數為 Y ;需要 inactive redo 數為 X ;每組日誌大小為 Z FAST_START_MTTR_TARGET 設定值為 M LOG_CHECKPOINT_TIMEOUT LOG_CHECKPOINT_INTERVAL 不能設定)

     M=(Y-X)*Z/N

     這樣就可以從機制上來控制 inactive redo 數量。


換句話說,只要比較 v$instance_recovery 中的 actual_redo_blks 是否小於當前 sum(active redolog blocks) 就可以!

如果小於,代表 DBWR 在不斷推進 incremental checkpoint ,這種情況下沒有問題;反之如果 actual_redo_blks 在不斷增加,而且和 sum(active redolog blocks) 相當,代表資料庫出現問題。如果 inactive redolog < 2 組,則資料庫會 hang




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

相關文章