log buffer及日誌管理深入分析及效能調整(七)

聽海★藍心夢發表於2009-03-17

其他相關的等待事件

       當程式需要向日志緩衝區裡複製重做記錄時,發現沒有足夠的可用空間時,則必須等待log buffer space事件。如果一個程式花費了太多的時間在log buffer space等待事件上,這通常是由於下面兩個原因:
<!--[if !supportLists]--&gt1)     <!--[endif]--&gt日誌緩衝區尺寸太小。對於一個繁忙的批處理系統裡,一個太小的日誌緩衝區(小於512K)會導致程式等待log buffer space
<!--[if !supportLists]--&gt2)     <!--[endif]--&gtLGWR程式太慢了,這也就是物理I/O速度過慢。可以透過檢查log file parallel write等待事件的平均等待時間來判斷,如果大於10毫秒,則說明LGWR過慢。
可以透過增加日誌緩衝區的尺寸或加快LGWR的程式來減少log buffer space等待事件。
 
       而較小尺寸的聯機日誌檔案會引起log file switch completionlog file switch (checkpoint incomplete)
這兩個等待事件。log file switch completion表示程式正在等待日誌切換完成。而當應用程式產生很多重做,然後由LGWR程式非常快得寫日誌檔案並進行日誌切換時,這時DBWR程式還沒有把髒資料塊寫入磁碟以通知checkpoint結束時,這個時候產生log file switch (checkpoint incomplete)等待事件。可以透過增加聯機日誌檔案的尺寸來減少log file switch completionlog file switch (checkpoint incomplete)
 
       使用如下來顯示有關日誌緩衝區的latch freemisrate是否很大。

select name,gets,misses,to_char((misses/(gets+misses)) * 100,'990.99') misrate

from v$latch where name in ( 'redo allocation' , 'redo copy', 'redo writing')

如果是redo copy的丟失率很嚴重,則可以考慮增加隱藏引數:_log_simultaneous_copies的值。該引數定義了redo copy latch的數量,該引數預設為CPU數量的兩倍。從8i起,該引數成為隱藏引數,因為不適合為系統增加過多的redo copy latch,特別是在OLTP環境中。增加該引數可以減少前臺對redo copy latch的等待,但是要注意,過多的redo copy latch可能會使得LGWR等待更長的時間。因為前面我們已經知道,LGWR在確定了要寫哪些日誌塊以後,會等待前臺程式完成對這些日誌塊的操作以後,才開始正式寫入。所以,如果很多的前臺程式都可以獲得redo copy latch以後,就可能引起LGWR要等很長時間才能開始正式寫入。

如果是redo allocation的丟失率很嚴重,需要考慮是否有可能減少重做記錄的生成。具體可以看下面有關如何減少重做記錄的部分。8i以前,存在一個引數:log_small_entry_max_size,該引數說明了當重做記錄的尺寸小於該引數指定值時,使用redo allocation latch來保護重做記錄複製到日誌緩衝區的過程,否則,如果重做記錄大於該引數值時,使用redo copy latch來保護這個過程。但是從8i以後,取消了該引數,只要複製重做記錄到日誌緩衝區,就獲得redo copy latch

如果是redo writing的丟失率很嚴重,則說明LGWR寫的時間過長,導致其他程式無法獲得該latch。這時可以透過減小_log_io_size來增加LGWR寫的頻率。具體_log_io_size的用法可以參考下面log buffer的設定部分。

的設定

對於日誌緩衝區來說,設定過小,容易引起log buffer space等待事件。但也不是說設定的越大就越好的,設定過大,由於LGWR程式會不斷啟動重新整理日誌緩衝區從而釋放記憶體,所以可能會根本用不上多餘的記憶體,從而浪費記憶體。

設定合適的日誌緩衝區大小,目的是為了能夠讓LGWR程式合理的觸發。理想情況下是,一方面,在LGWR程式向聯機日誌檔案中寫重做記錄時,日誌緩衝區中還是有剩餘的可用空間以供其他程式所使用;另一方面,當LGWR程式完成時,日誌緩衝區中的剩餘可用空間不要很多,因為這時LGWR所寫入日誌檔案的日誌塊就可以釋放出來了,成為新的剩餘可用空間。然後,LGWR可以再次啟動重新整理髒的日誌塊。如此良性迴圈,就能在滿足效能的前提下,充分利用日誌緩衝區。沒必要盲目的把日誌緩衝區設定的很大,完全可以把節省下來的記憶體交給比如資料塊緩衝區(buffer cache)等這樣更需要記憶體的元件。

我們已經知道,當重做記錄達到日誌緩衝區的1/31M時,就會觸發LGWR程式。也就是說,預設認為LGWR程式在寫日誌緩衝區大小的1/31M的重做記錄的過程中,剩下的日誌緩衝區可以供新的重做記錄的需要。當LGWR寫完以後,那麼這1/31M的日誌緩衝區就又可以成為可用的日誌塊以容納新的重做記錄了。由此,我們可以很容易推匯出,當我們設定日誌緩衝區達到3M3×1M)以上時,這時多餘出來的日誌緩衝區實際上並不能用得上,換句話說,多餘出來的記憶體就被我們浪費了。

不過,本質上,這個啟動LGWR的限度值是由一個隱藏引數:_log_io_size決定的,如下所示。該參數列示日誌緩衝區中存在多少個髒日誌塊時觸發LGWR程式寫髒日誌塊。預設情況下,該引數為0,表示當髒日誌塊佔日誌緩衝區的1/3時觸發LGWR程式。如果設定了該引數為一個非0值,則如果該引數值不大於日誌緩衝區大小的1/2時,該引數值作為啟動LGWR的限度值。否則,如果該引數值大於日誌緩衝區的1/2時,忽略該引數值,以日誌緩衝區大小的1/2為啟動LGWR的限度值。不管怎麼樣,髒日誌塊的容量只要超過1M,就必然觸發LGWR程式。

SQL> select x.ksppinm, y.ksppstvl, x.ksppdesc from x$ksppi x , x$ksppcv y

 2 where x.indx = y.indx and ksppinm like '%_log_io_size%';

KSPPINM      KSPPSTVL  KSPPDESC

------------- ---------- -------------------------------------------------------

_log_io_size 0         automatically initiate log write if this many redo blocks in buffer

在設定日誌緩衝區時,可以參考下面這個建議的公式來計算:1.5×(平均每個事務所產生的重做記錄大小×每秒提交的事務數量)

首先先找到總事務量是多少:

select a.value as trancount from v$sysstat a,v$statname b

where a.statistic# = b.statistic# and b.name = 'user commits';

然後,找到系統總共的執行時間:

select trunc(sysdate - startup_time)*24*60*60 as seconds from v$instance;

             第三,找到所產生的所有重做記錄大小:

select value as redoblocks from v$sysstat where name = 'redo blocks written';

最後,我們可以分別計算公式中的值:平均每個事務所產生的重做記錄大小= redoblocks/trancount;每秒提交的事務數量=trancount/seconds這樣,最後所建議的日誌緩衝區的大小可以寫為:

1.5* (redoblocks/trancount)* (trancount/seconds)

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

相關文章