Oracle完全檢查點和增量檢查點詳解

shilei1發表於2019-07-10

由於中LGWR和DBWR工作的不一致,Oracle引入了檢查點的概念,用於同步,保證資料庫的一致性。在Oracle裡面,檢查點分為兩種:完全檢查點和增量檢查點。下面我們分別介紹這兩種檢查點的作用:
ap C(Z+r%M26700801
.q eWb!d^&T267008011、完全檢查點
/soN:`-],[26700801ITPUB個人空間$D4gi:izZ q
在Oracle8i之前,資料庫的發生的檢查點都是完全檢查點。完全檢查點會將資料緩衝區裡面所有的髒資料塊寫入相應的資料檔案中,同時將最新的checkpoint scn更新到所有的資料檔案頭部及控制檔案。保證資料庫的處於一致的狀態。需要注意的是,完全檢查點產生的時候,CKPT並不是把當前完全檢查點發生那一時刻的SCN更新到控制檔案和資料檔案頭,而是將這個觸發檢查點時刻DBWn當前剛寫完dirty buffer對應的SCN更新到控制檔案和資料檔案頭,也就是說,更新控制檔案和資料檔案頭的SCN是滯後於完全檢查點的發生那一時刻的SCN的,這個從的原理也很容易理解,因為檢查點發生的時候要寫入dirty buffer還沒有寫入,自然不能立即更新成當前的SCN了。需要注意的是, 在oracle8之前,由於沒有chekpoint queue,也沒有增量檢查點的概念,發生完全檢查點時,DBWn會以一種無序的方式將所有的dirty buffer寫出到資料檔案,這個時候Oracle會凍結所有DML操作等候所有dirty buffer被寫出,巨大的IO往往會影響到資料庫的效能。後來隨著Oracle資料庫的發展和buffer cache的不斷增大,oracle 意識到這個單一的Full checkpoint機制已經不能滿足需要,所以在Oracle 8i後提出增量檢查點的概念,建立了checkpoint queue ,讓dirty buffer header根據首次變化時候的順序(LRBA)排列在queue裡面。 這樣DBWn只要順著queue的順序寫,而其他程式不必等候dbwr的寫完成就可以繼續。 因此增量檢查點的概念就由此產生了。ITPUB個人空間CXk/[5x5|;d5D1MM
ITPUB個人空間P3Jayem6I
完全檢查點在8i之後只有在下列兩種情況下才會發生:ITPUB個人空間 @?2w,tY-I+P;o D j
ITPUB個人空間?}3`Y\
DBA手工執行alter system checkpoint的命令;
^)Q+^b/}Z26700801
){ IHU@26700801資料庫正常shutdown (immediate,transcational,normal)。
1Y"z ~jgEf9P)g26700801
~ Wdw9tl xe@26700801ITPUB個人空間S8wav q

f1n|c3C ?U267008012、增量檢查點
y eo,f_8^bV9y26700801
ITPUB個人空間l [ y"Y ]5c
說白了,就是ITPUB個人空間 ?'P~u6@#Y*j

:b.f8nc!U_4?k26700801
CKPT每3秒一次的檢查DBWn寫進度並在控制檔案中記錄檢查點位置(checkpoint position)和更新heartbeat資訊
ITPUB個人空間)L&t,S*D3O3h9aT
ITPUB個人空間9_5y \6Q\4} C9G
以及
*} ON9A?$[26700801ITPUB個人空間oe5j"i?2O0X[b
CKPT定期觸發DBWn去寫checkpoint queue中的髒資料ITPUB個人空間^6[6A*v)MR-T

+?MP$g;|M@5A(i26700801
這兩項操作合一起被稱為增量檢查點。 --&gt可能這塊描述的過於籠統,大家繼續往下看:-)ITPUB個人空間;s!D9\KVR)\-{:n|P
ITPUB個人空間V!vuZJzJ*jQ
我們都知道被修改過的資料塊,在oracle中都被統稱為髒資料塊(dirty buffer)。所有的髒塊被一個連結串列串起來,稱做檢查點佇列(checkpoint queue)。在buffer cache中,每一個塊都有一個buffer header簡稱BH, 在BH中有一個ckptq項, 此專案中記錄了指向檢查點佇列上一個塊和下一個塊的指標。 如果某一個塊不在檢查點佇列中,他的ckptq項為空.透過ckptq項oracle將所有的髒塊串成了一個雙向連結串列。這個雙向連結串列就是檢查點佇列了。
C1GK-j+h26700801
/lWKN:Dt26700801Oracle從8i開始引入了檢查點佇列(checkpoint queue)的概念,用於記錄資料庫裡面當前所有的dirty buffer的資訊,這些dirty buffer的資訊按被修改的時間先後存放在checkpoint queue裡面(當塊首次被更改時,塊會立即被加進檢查點佇列),所涉及的條目主要包含RBA (Redo Block Address,重做日誌裡面用於標識事務期間資料塊在重做日誌裡面發生更改的編號)和資料塊的資料檔案號和塊號。ITPUB個人空間Q4vZ)AlN
ITPUB個人空間&pcz6jd
不論資料塊(buffer)更改幾次,它在checkpoint queue裡面的位置始終保持不變,checkpoint queue也只會記錄它最早的RBA(這個最早的RBA其實就是Low RBA,也就是資料塊第一次被修改時所對應的RBA),從而保證最早更改的資料塊能夠儘快從記憶體寫入資料檔案。DBWR每到一定的時機,就會被觸發(DBWn並不是只有當檢查點發生的時候才寫,它大約有10幾種條件觸發寫操作),沿著檢查點佇列的順序重新整理髒塊,同時CKPT程式,會監控著檢查點佇列的長度,當檢查點佇列的長度達到一定限制時(具體有幾個引數來確定checkpoing queue的長度,下面會提到比如log_checkpoint_timeout,fast_start_mttr_target等),CKPT會通知DBWR寫髒塊。CKPT會根據幾個引數的設定和I/O的速度以及繁忙程度,計算出來一個Target rba(目標rba),DBWn會沿著檢查點佇列,按照dirty buffer的Low RBA順序將所有Target rba之前對應的髒塊從記憶體寫入資料磁碟檔案。當CKPT通知完DBWn Target rba後,CKPT的任務就結束了。他並不會等待DBWn寫完所有的Target rba之前的髒塊。因此這裡CKPT只是起到了一個通知DBWn程式寫入的作用。ITPUB個人空間 Z;WH-r*Y3h0R8J

3@ r(Gv*hX*X26700801完全檢查點發生的時候,Oracle一方面通知DBWn進行下一批寫操作,另一方面是將這個觸發檢查點時刻DBWn當前剛寫完dirty buffer對應的SCN寫入資料檔案頭和控制檔案,這個SCN就是checkpoint scn。但Oracle考慮到檢查點SCN的間隔還是太大了,因為檢查點的觸發條件有限,週期可能比較長,有些情況下比如檢查點需要5分鐘左右才觸發,那這個時候系統crash再重新啟動就意味著很可能系統需要5分鐘左右才能啟動。於是Oracle採用了一個heartbeat的概念,以3秒的頻率將DBWn寫的進度反應到控制檔案中,這樣系統crash重新啟動的時候將從更近的一個時間點開始恢復。Oracle這麼做的目的就是要縮短崩潰恢復時間!因此CKPT另外一個任務就是每3秒,檢測一次DBWn的寫進度。DBWn是沿著檢查點佇列寫髒塊,由於這裡有一個順序的關係,所以DBWn的寫的進度就是可衡量的,寫到哪個buffer的時候該buffer的首次變化時候的scn(對應了LRba)就是當前所有資料檔案block的上面最新scn,但是由於無法適時的將DBWn的進度記錄下來,所以Oracle選擇了一些策略。 其中就包括CKPT程式的檢查點位置更新和心跳,所以說CKPT每3秒鐘檢視一下DBWn沿檢查點佇列寫到了哪裡,並且將這個位置設定為檢查點位置(checkpont position)。也就是說檢查點位置之前的塊,都是已被DBWn重新整理到磁碟上的塊因此我們可以理解為,CKPT程式每3秒會根據DBWn寫的進度設定並記錄一個檢查點位置,也就是說這個檢查點位置就是由DBWn的在往Target RBA寫過程中的進度決定的(如果沒有dirty buffer產生,那麼就不會更新檢查點位置資訊)。因此CKPT每3秒會將檢查點位置對應的資料塊的rba (low cache rba-表示Instance Recovery時開始恢復的日誌條目)更新和記錄到控制檔案的CHECKPOINT PROGRESS RECORDS區域,當然同時被記錄進控制檔案的還有heartbeat等其他資訊。DBWn將檢查點佇列裡面的dirty buffer寫入到資料檔案後,檢查點的位置也要相應地往後移。


-IaY$rngNE,^z1]26700801檢查點位置(checkpoint position)實際上就可以直接理解為是一個rba,他指向著重做日誌檔案中的某條重做記錄。在此檢查點位置前的重做記錄,其對應的buffer cache中的dirty buffer已經被寫進了資料檔案,在此位置後的重做記錄,所對應資料髒塊有可能還在記憶體中。如果發生了例項崩潰,只需要在日誌檔案中找到檢查點位置(low cache rba),從此處開始應用所有的重做日誌檔案,就完成了前滾操作。例項崩潰後,再次啟動資料庫,oracle會到控制檔案中讀取low cache rba,這就是檢查點位置。從此處開始應用重做日誌,應用到on disk rba的位置。on disk rba是磁碟中重做日誌檔案的最後一條重做記錄的rba。如果某條重做記錄的rba高於on disk rba,那說明此重做記錄還沒有被寫進日誌檔案中,崩潰發生時,他是不可能被恢復的。on disk rba是oracle前滾操作的終點。比這個更高的rba,都應該還駐留在log buffer中。還沒有被LGWR寫入日誌檔案。所以是不能被用於恢復的。
R H(s%N6\2vA26700801ITPUB個人空間 Hju Vq$B#AB
在DBWn寫dirty buffer這個檢查點過程中,Oracle也可以繼續產生dirty buffer,DBWn也不是一次要把所有dirty buffer全部寫到磁碟(不同於完全檢查點的地方),這樣就提高了檢查點的效率,使得資料庫要做恢復的時候從這個最新位置開始做恢復,而不是從資料檔案中的checkpoint scn(上一個完全檢查點位置) 開始做恢復,這樣將縮短恢復時間。ITPUB個人空間M'ZNa%H7V&Q

aR7{'R!YFcf26700801Oracle的Concept裡面提到:An incremental checkpoint is a type of thread checkpoint partly intended to avoid writing large numbers of blocks at online redo log switches. DBWn checks at least every three seconds to determine whether it has work to do. When DBWn writes dirty buffers, it advances the checkpoint position, causing CKPT to write the checkpoint position to the control file, but not to thefile headers.
&\vr @;T!UOg26700801因此我們需要注意的是:增量檢查點並不會去更新資料檔案頭,以及控制檔案中資料庫SCN以及資料檔案條目的SCN資訊,而只是每3秒由CKPT程式去更新控制檔案中的low cache rba資訊,也就是檢查點的位置。ITPUB個人空間U7q)hNlh'`
ITPUB個人空間'h;@qXK0r;M5S%}
檢查點位置發生變更後, Oracle主要透過4個引數和1個機制來控制檢查點位置和最後的重做日誌條目之間的距離(檢查點佇列的長度)。
C B4{T%{#Fu26700801ITPUB個人空間 {b+y4a"Am G#I*E
fast_start_io_target (Oracle 9i以後已經廢棄)
4b`.oV9Ko26700801
JW/ll[ ikX7cE26700801該引數用於表示資料庫發生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。
|5E X|m$e26700801
+i7xA&nvBeK0[26700801fast_start_mttr_target
[!h5s~%P7m26700801
|T@W%y3N%f26700801我們從上面可以看到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廢除了。
~9z a$V4|p3u+PbH26700801ITPUB個人空間&m(`$I1SOCA
log_checkpoint_timeoutITPUB個人空間N E{E,}G5cT%C

"m)dliNY26700801該引數用於表示檢查點位置和重做日誌檔案末尾之間的時間間隔,以秒為單位,預設情況下是1800秒。相比fast_start_mttr_target,它也是時間,但它的時間值表示完成恢復操作所需要的時間,即從最後的檢查點位置開始,應用所有日誌直到日誌末尾所需要的時間。而本引數log_checkpoint_timeout表示從最後的檢查點位置開始,到日誌末尾經過的時間。ITPUB個人空間 A gD"g-K.e.wI

;Ja&w6i@)i-[6K&f26700801log_checkpoint_intervalITPUB個人空間._G"D(ML;R[S
ITPUB個人空間enI#J ^~f!l
該引數是表示檢查點位置和重做日誌末尾的重做日誌塊的數量,以OS塊表示。
/~'{np R.g.lAIG26700801ITPUB個人空間j*Z$HP.c?6`
90% OF SMALLEST REDO LOG

K%k6Q*}5vA;e26700801
[ Qq tb)SE26700801除了以上4個初始化引數外,Oracle內部事實上還將重做日誌檔案末尾前面90%的位置設為檢查點位置。在每個重做日誌中,這麼幾個引數指定的位置可能不盡相同,Oracle將離日誌檔案末尾最近的那個位置確認為檢查點位置。
-j7sy,Y[{a26700801ITPUB個人空間)]-k D0ib@{Jo
在Oracle 9i後,對檢查點頻率,建議只設定fast_start_mttr_target。根據需要,也可以透過設定log_checkpoint_timeout,設定一個髒塊保持髒狀態的最大時間,而其他兩個引數fast_start_io_target,log_checkpoint_interval建議不再使用。ITPUB個人空間G4R WW.^*[

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

相關文章