當Oracle發起一個事務需要更改數據時,如果所涉及的數據塊不在BUFFER CACHE中,那么Oracle服務進程首先會將相關數據塊從數據文件中讀進BUFFER CACHE進行更改(直接路徑讀除外),更改后的數據塊被稱為臟塊(DIRTY BLOCK)。當事物提交或者回滾時,基于性能上的考慮,臟塊并不會立刻寫至數據文件,而是由LGWR進程優先將臟塊的信息寫至ONLINE REDOLOG,只有當LGWR進程返回寫成功之后,事務才算提交成功。這就是Oracle為了保證不丟數據的“日志優先寫”原則。提示 為了保證數據不丟失,LGWR進程寫REDOLOG時,一般會采用同步I/O。
日志寫優先的問題
“日志優先寫”原則帶來的問題就是當數據庫異常宕機時,可能會仍有部分臟塊在BUFFER CACHE的臟緩沖區列表中,并沒寫進數據文件。
實例前滾及后滾(先前滾后回滾)
前滾:通過redolog重構未寫進數據文件的臟塊信息,通知DBWR進程將臟塊寫進數據文件
回滾:回滾異常宕機時未提交的臟的數據塊,未回滾的事務,通過掃描undo進行這些事務的回滾。
啟動數據庫時,首先會由服務器進程進行實例恢復(CRASH RECOVERY,又叫前滾),即服務器進程掃描ONLINE REDOLOG,在BUFFER CACHE中重構未寫進數據文件的臟塊信息之后,會通知DBWR進程將臟塊寫進數據文件。CRASH RECOVERY完畢以后,BUFFER CACHE里既有數據庫異常宕機時已經提交還沒有寫入數據文件的臟數據塊,又包含了事務被突然終止,以致既沒有提交又沒有回滾的事務所弄臟的數據塊。CRASH RECOVER完成操作之后則由SMON進程掃描UNDO段頭進行事務恢復(TX RECOVERY,又叫后滾),最終將數據庫恢復至宕機前的那一刻。圖4-4清晰地展示了這一過程。
由前面分析可知,除去硬件性能等因素以外,數據庫打開的速度受兩個自身因素影響:
◆ 在線日志(ACTIVE和CURRENT狀態)所對應的臟塊數量。臟塊數量越多,數據庫恢復的時間就越長,數據庫打開速度越慢。需要恢復的臟塊的數量可以在CRASH RECOVERY日志中看到,如下所示:
Sat Jul 28 22:27:47 2012
Completed redo scan
134146 redo blocks read,8902 data blocks need recovery
◆ 需要恢復的事務的數量和大小。事務數量越多,事務越大,數據庫打開越慢。為加快事務恢復速度,后臺進程往往采用并行恢復,其并行度主要受參數
fast_start_parallel_rollback影響。
CHECKPOINT優化
Oracle引入增量CHECKPOINT的目的是將BUFFER CACHE中的臟塊寫操作分散到不同的時間點完成,但在I/O壓力比較大的業務系統下,過于頻繁的臟塊寫操作顯然會給系統帶來額外的負擔,甚至影響業務系統的響應時間,那么我們需要對此進行一些優化,我們不能改變CHECKPOINT的算法,但是可以減少DBWR進程寫臟塊的頻率。以下便是業務系統在不同I/O壓力下的優化思路。
在I/O壓力比較大的系統中,建議設置參數FAST_START_MTTR_TARGET為0或者將參數設置成較大值(如3000),從而降低DBWR寫臟塊的頻率,使得臟塊盡可能地保存在BUFFER CACHE中。對于ONLINE REDOLOG,如果其大小過小,容易引起在線日志的頻繁切換,從而導致頻繁的CHECKPOINT。為緩減I/O壓力,在日志量較大的系統中,可以設置比較大的ONLINE REDOLOG(比如2GB或者4GB)。如果系統內存充足,建議設置較大的BUFFRE CACHE,不但更多的數據塊可以保存在緩沖區中,而且可以進一步減少增量CHECKPOINT的頻率。如果觀察到DBWR進程比較繁忙(比如該進程CPU占用率較高),則可以設置db_writer_processes參數增加DBWR進程數量,從而加快CHECKPOINT速度。
提示 一般情況下,日志切換維持在20分鐘左右比較合適。
在I/O壓力較小的系統中,建議不要設置參數FAST_START_MTTR_TARGET(事實上Oracle默認就不設置該參數)。實踐經驗表明,數據庫在異常宕機后的啟動過程中,掃描和應用ONLINE REDOLOG的速度一般都能在幾分鐘內能完成。ONLINE REDOLOG的應用速度不僅跟臟塊數量有關,還跟掃描數據文件頭的數量有關,數據文件越多,其掃描速度越慢。
參考《DBA實戰攻略》