redo機制詳解——做好數據的第一層安保

    僅僅是個人對redo運行機制的理解,不對的地方,希望筒子們指出,共同學習。如果你想讓你對redo的理解更加清晰,那麼可以選擇繼續看下去。

redo存在的根本意義:

    大家都知道數據庫修改數據是在buffer cache中進行修改的,然而在commit之後,並不會馬上寫入數據文件(no-force-at-commit策略),因爲這樣零散的寫出非常消耗資源,而且IO從來都是最有可能是性能瓶頸的地方,但是爲了保證提交後的數據能夠在故障後可以被恢復,這就產生了redo機制,通過將數據庫的修改操作記錄到redo log buffer中,寫出到redo文件中,來推遲數據的寫出,達到批量處理的效果,提高了效率。所以redo 對於數據庫是極其重要的。

redo機制的組成:

   redo機制,包含三大組件:redo log buffer,LGWR後臺進程,redo log file日誌文件(如果歸檔模式下還有arch後臺進程以及歸檔

日誌文件);

   如果每產生一次redo就要寫入到redo log file中,這同樣也會產生IO的問題,同時在高併發的環境下還會引發redo log file的爭用,所以就產生了 redo log buffer(oracle分配的一塊內存區域,存在於SGA中,循環使用),但是該內存區域是循環使用的這就需要一個後臺進程來不斷的將log buffer 中的內容寫出到redo log file中,這也就是LGWR的作用,同時 redo log file同redo log buffer一樣也是循環使用的,那怎麼來保證數據的安全性呢? 所以每次log switch的時候都會出發一次檢查點,促使DBWR進程將寫滿的redo log file保護的髒數據寫出到數據文件中,這樣在檢查點完成之後,redo log file 就變成了 inactive 狀態,就可以被清空重用了。

redo 機制詳解:

redo log buffer:

    redo entries(redo 條目):包含了重構,重做數據庫的變更信息,這些信息包括update,insert,delete,drop,alert,create 等;

    一個redo 條目,是在用戶全局區(PGA)中產生的,然後由oracle服務進程拷貝到redo log buffer中去,再一定條件下由LGWr後臺進程寫入到redo log file中。由於redo log buffer是共享的內存區域,在高併發的系統中,可能會出現redo log buffer爭用的情況,這就產生了latch機制,log buffer由redo_allocation_latch保護,服務進程必須先獲取到redo_allocation_latch才能分配相應log buffer;

  redo條目寫入到redo log buffer的過程如下:

wKiom1R_8x_zYvzAAACfVOnDmu8010.jpg

1>redo並行機制:  

     高併發的環境下,必然會redo_allocation_latch的爭用(redo log buffer 只有一個redo_allocation_latch),爲了減少redo_allocation_latch的等待,在oracle9.2中,引入了log buffer的並行機制。 

2>Share strand:

     將log buffer劃分成多個小的buffer,這些小的buffer稱作strand,也叫shared strand,每個strand有一個redo_alloction_latch的保護,以前順序的redo buffer的分配變成了現在的多個strand出現以後的並行的過程,大大提高了效率。 

3>Priate strand:

     爲了進一步提高降低redo buffer的爭用,oracle10g引入了一個新的機制---priate strand,priate strand不是在PGA中產生的,而是在share pool中分配的一塊共享內存區域,每個priate starand由一個redo_allocation_latch保護,而每個priate strand只會服務於一個活動的事務,獲取到priate strand的事務,不會再PGA中產生redo,而是在priate strand中產生,當flash priate strand或者commit的時候,priate strand將被批量寫入到redo log file中;如果事務獲取不到priate strand,那麼將會繼續遵循舊的log buffer機制,即shared strand,所以當告警日誌出現Private strand flush not complete  可以選擇忽略不管。

     上面提到,priate strand會在flush/commit的時候直接寫入到redo log file,而不經過redo log buffer,這就減少了對share strand的redo_allocation_latch的申請,提高了效率;

     priate strand的過程如下:     

wKioL1R_87zxOFtkAADbWcTL0qw853.jpg

注意:在沒有獲取priate strand的redo_allocation_latch成功的事務結束前,即使有其他的事物結束釋放latch,該事物也不會再去申請priate strand的redo_allocation_latch;

LGWR後臺進程:

    Redo log buffer 是一塊共享的循環使用的內存區域,LGWr就負責適時的將其髒的日誌快釋放掉,提供新的日誌快供下次使用。其是順序寫入日誌文件中,而不像DBWr那樣隨機寫入,所以速度快的多;

LGWr的觸發條件:

  • commit/rollback語句操作的時候

  • 當整個日誌信息的數量達到日誌緩衝區的1/3時,或者日誌信息數量達到1M的時候會觸發LGWr,這兩個觸發條件都是因爲一個隱藏

  • 參數_log_io_size來定的,所以如果LGWr觸發頻繁的情況,可以選擇將該參數設置成3M,這樣1/3和1M便成了一個觸發條件了。

  • 每個3秒觸發一次

  • 當DBWr被觸發,寫出數據之前,會判斷該部分數據信息有沒有記錄到日誌文件,如果沒有,便會將需要寫入日誌的block放入一個

  • 隊列中,觸發LGWr去寫出,完成後DBWr纔會繼續寫出數據到數據文件。

redo log file:

相關的視圖:

SELECT * FROM v$log;

SELECT * FROM v$logfile;

SELECT * FROM v$archived_log;

SELECT * FROM v$recover_file;

SELECT * FROM v$log_history;

SELECT * FROM V$loghist;

重做日誌文件狀態:

  • UNUSED :表示該聯機重做日誌文件組對應的文件還從未被寫入過數據,通常剛剛創建的聯機重做日誌文件組會顯示成這一狀態。當日志切換到這一組時,就會改變狀態

  • CURRENT :表示當前正在使用的日誌文件組。該聯機重做日誌組是活動的。當前Oracle數據庫正在使用的聯機重做日誌文件組。

  • ACTIVE : 表示該組是活動的但不是當前組,實例恢復時需要這組日誌。如果處於這一狀態,表示當前日誌組正在歸檔,如果當日志切換的時候全備都是active狀態,就會在告警日誌中產生     checkpoint not complete信息,並且伴隨着cannot allocate new     log的錯誤信息, 反應到等待事件就是log file sync;

  • INACTIVE:表示實例恢復已不再需要這組聯機重做日誌組了。表示對應的聯機重做日誌文件中的內容已被妥善處理,該組聯機重做日誌當前處於空閒狀態

  • CLEARING:表示該組重做日誌文件正被重建(重建後該狀態會變成UNUSED)。

  • CLEARING_CURRENT:表示該組重做日誌重建時出現錯誤。

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