1. 程式人生 > >oracle之 等待事件LOG FILE SYNC (awr)優化

oracle之 等待事件LOG FILE SYNC (awr)優化

dlink append 訪問性 wak date 告訴 wakeup 優先級 led

log file sycn是ORACLE裏最普遍的等待事件之一,一般log file sycn的等待時間都非常短 1-5ms,不會有什麽問題,但是一旦出問題,往往都比較難解決。什麽時候會產生log file sync等待?
常見有以下幾種:
1)commit操作
2)rollback操作
3)DDL操作(DDL操作實施前都會首先進行一次commit)
4)DDL操作導致的數據字典修改所產生的commit
5)某些能遞歸修改數據字典的操作:比如查詢SEQ的next值,可能會導致修改數據字典。一個典型的情況是,SEQ的cache屬性設置為nocache,那麽會導致每次調用SEQ都要修改數據字典,產生遞歸的commit。

一個正常的系統裏,絕大多數的log file sycn等待都應該是上面描述的1)commit操作 造成的log file sycn等待,某些異常的系統,比如頻頻rollback、seq的cache設置為nocache的系統,也可能會造成比較多的log file sycn等待。

我們要是能知道log file sync包含哪些環節,再有針對性的優化各個環節,就能事半功倍了。
技術分享


上面是Tanel Ponder畫的log file sync等待事件的延遲圖,在某些關鍵環節上打了點。我對其中打點的環節,稍作翻譯如下:
1)用戶進程發起commit
2)用戶進程通知lgwr寫日誌
3)lgwr接收到請求開始寫
4)lgwr寫完成
5)lgwr通知用戶進程寫完成
6)用戶進程獲得通知,繼續做其他事

1,2階段的時間,主要是post/wait的時間,典型的這種post/wait一般利用的是操作系統的信號量(IPC)實現,如果系統CPU資源充足,一般不會出現大的延遲。前臺進程post lgwr後,就開始等待log file sync。
2,3階段的時間,主要是lgwr為了獲取cpu資源,等待cpu調度的時間,如果系統cpu資源充足,一般不會出現大的延遲。這裏我們需要知道,lgwr只是操作系統的一個進程,它需要操作系統的調度獲取cpu資源後才可以工作
3,4階段的時間,主要是真正的物理io時間,lgwr通知os把log buffer的內容寫入到磁盤,然後lgwr進入睡眠(等待log file parallel write),這個時間正常情況下的延遲占整個log file sync的大部分時間。還需要指出,lgwr在獲取cpu資源後,可能並不能馬上通知os寫磁盤,只有在確保所有的redo copy latch都已經被釋放,才能開始真正的IO操作。
4,5階段的時間,os調度lgwr 重新獲得cpu資源,lgwr post前臺進程寫完成。lgwr可能會post很多前臺進程(group commit的副作用)
5,6階段的時間,前臺進程接受到lgwr的通知,返回cpu運行隊列,處理其他事物(log file sync結束)。

/*************************************************什麽是group commit************************************************/
不止一次的看到過一些對log file sync調優的建議裏寫著:打開ORACLE的組提交功能。
group commit默認就是開啟的,而且你沒有任何手段可以關閉它!
我一直認為group commit這個東東起的名字不是太過恰當,應該起組刷新更恰當,僅僅代表個人意見。
什麽是組提交?
技術分享

上圖是log buffer的抽象圖,log buffer此時是非常繁忙的。
給大家設定這樣一個場景。
c1作為一個commit record已經被copy到了log buffer裏,接著前臺進程通知lgwr去寫日誌,根據我前面的描述,在前臺進程post lgwr去寫,到lgwr真正開始寫之前,非常可能存在著時間差,就在這個時間差裏,c2,g1,c3也已經把相應的日誌拷貝到了log buffer裏,其中c1,c2,c3是commit的記錄,g1僅僅是普通的事務日誌,不是commit日誌。在lgwr真正開始寫之前,它會去檢查當前log buffer的最高點,發現在c3位置處,把這個點作為此次刷新日誌的目標,把c1,c2,g1,c3的日誌都刷新到磁盤。雖然刷新日誌這個操作是由c1出發的,但是c2,g1,c3也是受惠者搭了便車,日誌也被刷新到了日誌文件裏,這個功能叫組提交,對於一些不太熟悉ORACLE的人容易把組提交誤解為,把提交的事物打包刷新到日誌裏,其實LGWR是不管你的事務日誌有沒提交的,它只按照log buffer分配的最高點來刷新,因此我覺得叫組刷新更好點。
圖中c1,c2,g1的日誌已經拷貝完成,我用filled表示,c3的日誌空間已經分配,但是還沒完成拷貝,我用allo表示,這個情況下,其實lgwr需要等待c3日誌拷貝完成,才能真正的開始刷新操作。
/*************************************************什麽是group commit************************************************/





技術分享

我們剖析了log file sycn的各個階段後,可以看出,正常情況下,最慢的環節應該在3,4階段(如上圖),典型的io操作,這個環節對應的數據庫等待叫做log file parallel write。其他的階段如調度延遲、IPC時間一般都是極短的。網上、論壇上、包括不少書籍裏,很多在log file sync出現問題後,往往都把責任推卸到IO慢的原因上。絕大多數情況下,這樣的推斷可能都是正確的,但是,事情不總是這樣的,就像我們分析的,log file sync的快慢也是很依賴cpu資源是否富足、系統的負載是不是過大。我們再看下一幅圖,這副圖描述了,在CPU資源不足的情況下,各個階段占取整個log file sycn的比重。

技術分享

如你所見,由於CPU資源的不足、系統負載過大,導致操作系統調度出現了較大的延遲,3,4階段的IO部分的延遲已經不是整個log file sync時間的最大的罪魁禍首!

/*********************************************小插曲*****************************************************************************/
lgwr會post哪些前臺進程?
當lgwr刷新完日誌後,會post相應的前臺進程(wakeup)繼續工作,那麽lgwr怎麽判斷應該wakeup哪些前臺進程呢?
log file sync等待的p1參數的含義為:P1 = buffer# in log buffer that needs to be flushed
當lgwr刷新完buffer後,會掃描活躍會話列表,查看哪些會話在等待log file sync,而且會話的buffer#小於等於它所刷新的log buffer的最大值,這些會話會被wakeup。
/*********************************************小插曲****************************************************************************/

LOG FILE SYNC調優
作為通用的log file sync的診斷、調優方法,一般可以通過診斷系統的IO延遲為多大,cpu資源是否充足來判斷哪裏出現了問題。
IO延遲的診斷、調優:可以通過log file parallel write這個後臺進程等待事件來輔助判斷。如果這個等待時間過大,那麽你系統的IO很可能出現了問題。優化IO的手段一般為:RAID的方式不要為RAID5,最好為RAID10,關閉RAID卡的讀CACHE,全部用作寫CACHE,可以用2-4塊盤作為日誌的磁盤組,如果使用的是存儲,一般存儲機頭的CACHE也比較大,IO上基本能得到保障。使用ssd作為日誌組來提升IO並沒有什麽好的效果。可以通過 v$event_histogram視圖獲取log file sycn、log file parallel write等待事件的時間分布圖(後面有介紹)來輔助診斷。
cpu資源的診斷、調優:如果log file sync的時間與log file parallel write的時間差異過大,則可能系統的CPU資源出現了不足。solaris下還可以通過操作系統工具prstat來診斷lgwr進程的延遲時間,見下圖的LAT列。其他平臺不能直接針對進程進行跟蹤診斷,可以通過系統LOAD,CPU使用率來輔助診斷,如CPU使用率超過百分之六十可能就會造成一定程度的調度延遲、CPU運行隊列超過物理CPU的CORE數就有調度延遲的風險等等。如果系統的CPU資源出現瓶頸是比較棘手的,因為換硬盤尚且還算是執行起來不算費勁的,但是換CPU難度一般會比較大,最終可能的結果就是換主機。不過也有一些手段可以嘗試:調高LGWR的優先級,可以通過數據庫參數_high_priority_processes進行,或者操作系統命令renice命令進行(前者可能更好點)。調整LGWR優先級的目的是為了讓LGWR盡可能的容易獲得CPU資源,減少排隊調度時間。
調優應用:不過有時候更為有效的手段可能不是拼命的調優數據庫、調優硬件,比如:是不是可以合並事物,也就降低了LOG FILE SYNC的次數,變相的提高了系統事務的效率。
數據庫調優:通過設置ORACLE的REDO LOG 塊大小為4K來提升日誌寫的性能.11GR2的版本可以指定REDO LOG的塊大小。在我的版本11.2.0.3下修改會報錯,說修改值與實際扇區大小不匹配。通過修改隱含參數_disk_sector_size_override為true,可以強制改成功。修改的辦法是在alter database add log file xxxx blocksize 4096。如果拿PL/SQL壓測,采取commit write immediate wait方式提交,優化前後的差距接近4倍,非常驚人。但是拿我們的業務壓測,只是提升了1500+的TPS,也非常的不錯了。
內存調優:在AIX下,如果開啟內存預讀,對於提升TPS也是非常的明顯 dscrctl -n -b -s 1 。見http://space.itpub.net/22034023/viewspace-751590。

技術分享



/*****************************************************************************可憐的LGWR****************************************************************************/
如果有大量進程在等待LOG FILE SYCN,一旦LGWR寫完成,它將POST這些進程蘇醒,使它們重新進入CPU運行隊列,而LGWR會被當初post它寫日誌的進程push off出cpu運行隊列。這個情形下,由於LGWR已經工作了一段時間了(剛剛寫完日誌),而前臺進程已經等待了一段時間了(等待LOG FILE SYNC),根據操作系統的默認的調度策略,這種情況下,前臺進程將會有更高的優先級獲取CPU資源,而LGWR將可能由於CPU資源突發式的緊張而沒有獲取到CPU資源,導致系統 的事務數有很大的降低:因為LGWR已經不工作了(雖然時間很短)。因此我前面所建議的調高LGWR進程優先級的手段是值得嘗試的。
/*****************************************************************************可憐的LGWR****************************************************************************/

獲取log file sync、log file parallel write時間分布
如果我們僅僅觀察AWR報告,獲取log file sync、log file parallel write某一段時間的平均等待時間,有時候是不夠的,我們可能想更精細化的知道,10000次等待裏,有多少次等待是在1ms以內,有多少次是在2ms以內,等等。查詢V$EVENT_HISTOGRAM可以告訴我們這些信息,對於我們診斷性能問題非常有幫助。
SQL> select event, wait_time_milli,wait_count
2 from v$event_histogram
3 where event = ‘log file parallel write‘;
EVENT WAIT_TIME_MILLI WAIT_COUNT
------------------------- --------------- ----------
log file parallel write 1 22677
log file parallel write 2 424
log file parallel write 4 141
log file parallel write 8 340
log file parallel write 16 1401
log file parallel write 32 812
log file parallel write 64 391
log file parallel write 128 21
log file parallel write 256 6
如上,我們可以知道log file parallel write等待時間在1ms以內的有22677次,2ms以內的有424次,等等。
我們可以簡單的取兩次V$EVENT_HISTOGRAM的快照,來判斷間隔時間內,指標的變化次數來輔助我們診斷問題。(AWR思想)

LOG BUFFER 需要調優?
一般情況下,是不需要調優的!
10G以後,LOG BUFFER一般情況下已經比較大,一般為1到多個granules大小,除非你看到了比較多的log buffer space等待事件,否則不需要調整log buffer的大小。
9.2以後, LOG BUFFER根據你系統CPU的多少,已經被拆分成多個LOG BUFFER,很大程度上緩解了redo allocatoin latch的爭用,除非看到了明顯的redo allocation latch的爭用,否則不用調整log buffer的數量。
10G以後,私有redo和imu的出現,進一步降低了redo allocation latch的爭用。每一個私有redo都由一個私有的redo allocation latch保護。同上,一般情況不用調整。

redo相關latch需要調優?
redo copy latch:僅僅用來跟蹤是否有進程正在往log buffer裏拷貝數據。lgwr在真正開始寫之前,必須等待相關的進程拷貝完畢,在此期間,lgwr會等待LGWR wait for redo copy等待。可以同時向log buffer裏進行拷貝的進程的數量由_log_simultaneous_copies決定。
redo allocation latch:保護進程在redo buffer裏分配空間用的,保證各個進程間彼此分配的空間不重疊。
redo writing latch:這個latch其實保護的是一個標誌位,進程獲取這個latch後,修改標誌位,比如把0改為1,代表lgwr正在寫,這樣後續的提交進程,獲得這個latch後讀取標誌位,就知道當前LGWR是不是正在寫了,避免了很多不需要的重復通知。
我們知道了這幾個latch的作用,那麽我們需要調優他們嗎?
一般是不需要的,除非他們相關的等待已經引起了你的註意,而且ORACLE各個版本也一直在優化相關的latch的獲取和釋放,比如redo allocation latch,這一塊已經做的非常高效了。關於redo allocation latch發展史,查看我的另一篇文章:http://www.itpub.net/thread-1803010-1-1.html

新的調優手段
10GR1的時候,ORACLE公司默默的推出了一個參數:commit_logging,這個參數可以有四種組合:
commit write [batch|immediate][wait|nowait]
10GR2版本發布的時候,這個參數被拆成了2個參數,commit_logging,commit_write,個人認為10GR2拆分後的參數,更能準確表達參數的意圖。
我們先著重的看下commit_write這個參數,它的參數值可以為wait/nowait,代表:前臺進程事務提交的時候,通不通知LGWR去刷新日誌。wait為通知,前臺進程會等待log file sync。nowait為不通知,僅僅等待其他操作觸發lgwr去寫日誌(如3秒,1M大小,1/3滿)。如果你的業務對數據的一致性的要求不高,對ACID的D沒有要求,為了提高事物數、提高性能,你可以選擇commit_write為nowait方式。而在10G以前,ACID的D是必須滿足的,也就是說,前臺進程在提交的時候,是必須要等待LOG FILE SYNC,等待LGWR刷新日誌到磁盤的。
我們來簡單的看下commit_logging參數,參數可以選擇的值有batch/immediate,這個參數極其容易引起人的誤解,讓人誤以為batch的含義是,控制著事物以group commit的方式打包提交。immediate方式是代表讓事物一個個的提交,一次提交刷新一次log buffer,但是不是這樣的!
immediate與batch相比,commit的改變向量(修改回滾段頭的事務槽)將作為單獨的redo record產生,跟9I的commit記錄日誌的方式是一樣的。batch 模式下commit日誌的記錄方式是合並進事務的redo record裏,這個batch模式依賴使用私有redo和imu,如果他們關閉的情況下,batch的設置也就沒了作用。

我們對insert into a values(1111);commit;來進行dump log file,闡述一下batch/immediate方式的區別 :

DUMP LOG FILE:啟用私有redo和imu,設置commit_logging為immediate,commit的日誌作為單獨的redo record產生,一共2條redo record,第二個redo record為commit產生的,見紅色部分(OP:5.4,代表為UNDO段頭的修改)
REDO RECORD - Thread:1 RBA: 0x00044d.00000002.0010 LEN: 0x0230 VLD: 0x05
SCN: 0x0000.041b921c SUBSCN: 1 06/25/2013 11:27:32
(LWN RBA: 0x00044d.00000002.0010 LEN: 0002 NST: 0001 SCN: 0x0000.041b921c)
CHANGE #1 TYP:0 CLS:51 AFN:3 DBA:0x00c04c80 OBJ:4294967295 SCN:0x0000.041b91d1 SEQ:1 OP:5.2 ENC:0 RBL:0
ktudh redo: slt: 0x0016 sqn: 0x00002bee flg: 0x0012 siz: 136 fbi: 0
uba: 0x00d1a78d.0068.2c pxid: 0x0000.000.00000000
CHANGE #2 TYP:2 CLS:1 AFN:9 DBA:0x024002c5 OBJ:15750 SCN:0x0000.041b916a SEQ:1 OP:11.2 ENC:0 RBL:0
省略

REDO RECORD - Thread:1 RBA: 0x00044d.00000004.0010 LEN: 0x00d0 VLD: 0x05
SCN: 0x0000.041b921e SUBSCN: 1 06/25/2013 11:27:34
(LWN RBA: 0x00044d.00000004.0010 LEN: 0001 NST: 0001 SCN: 0x0000.041b921d)
CHANGE #1 TYP:0 CLS:51 AFN:3 DBA:0x00c04c80 OBJ:4294967295 SCN:0x0000.041b921c SEQ:1 OP:5.4 ENC:0 RBL:0
ktucm redo: slt: 0x0016 sqn: 0x00002bee srt: 0 sta: 9 flg: 0x2 ktucf redo: uba: 0x00d1a78d.0068.2c ext: 104 spc: 2050 fbi: 0

DUMP LOG FILE:啟用私有redo和imu,設置commit_logging為batch,commit作為一個改變向量合並進了事物的redo record裏,作為一條redo record,change #3為commit產生的。
REDO RECORD - Thread:1 RBA: 0x00044d.00000002.0010 LEN: 0x0230 VLD: 0x05
SCN: 0x0000.041b921c SUBSCN: 1 06/25/2013 11:27:32
(LWN RBA: 0x00044d.00000002.0010 LEN: 0002 NST: 0001 SCN: 0x0000.041b921c)
CHANGE #1 TYP:0 CLS:51 AFN:3 DBA:0x00c04c80 OBJ:4294967295 SCN:0x0000.041b91d1 SEQ:1 OP:5.2 ENC:0 RBL:0
ktudh redo: slt: 0x0016 sqn: 0x00002bee flg: 0x0012 siz: 136 fbi: 0
uba: 0x00d1a78d.0068.2c pxid: 0x0000.000.00000000
CHANGE #2 TYP:2 CLS:1 AFN:9 DBA:0x024002c5 OBJ:15750 SCN:0x0000.041b916a SEQ:1 OP:11.2 ENC:0 RBL:0
CHANGE #3 TYP:0 CLS:51 AFN:3 DBA:0x00c04c80 OBJ:4294967295 SCN:0x0000.041b921c SEQ:1 OP:5.4 ENC:0 RBL:0
ktucm redo: slt: 0x0016 sqn: 0x00002bee srt: 0 sta: 9 flg: 0x2 ktucf redo: uba: 0x00d1a78d.0068.2c ext: 104 spc: 2050 fbi: 0

個人感覺commit_logging參數的作用不大,可能有助於減少ACID的異常時間,對日誌量的size在batch模式下有輕微的減少。ACID異常見我的另一個文章:http://www.itpub.net/thread-1803010-1-1.html


PL/SQL commit優化
傳統情況下,當用戶發出commit後,用戶會話會等待log file sync直到lgwr寫完成。LGWR寫完成後,通知處於前臺進程繼續處理後面的操作。這個機制保障了事務的持久性,滿足了事務ACID的D。但是PL/SQL不是這麽工作的:PL/SQL裏的commit 操作不會等待lgwr寫完成就可以繼續處理後面的操作。簡單的看個例子:
begin
for r in (select id from t1 where mod(id, 20) = 0) loop
update t1 set small_no = small_no + .1 where id = r.id;
commit;
end loop;
end;
/
查看session 和 sys相關的統計信息如下:

user commits (session statistic) 25
messages sent (session statistic) 6
redo synch writes(session statistic) 1
log file sync (session events) 1
messages received (lgwr statistic) 6
redo writes (lgwr statistic) 6
log file parallel write (lgwr events) 6
Lgwr僅僅寫了6次(log file parallel write),用戶會話僅僅等待了log file sync一次。那意味著會話發出commit命令後,並沒有停下來等待lgwr寫完成,就繼續處理後面的事務了。用戶會話沒有遵守事務的持久化原則!!如果實例在PL/SQL處理的過程中crash,那麽某些提交的事務是不可恢復的。Oracle對此有一個貌似合理的解釋,在PL/SQL沒有處理完畢之前,你不知道已經提交了多少次,Oracle不會使他們可恢復,只有在PL/SQL結束的時候,增加redo sync writes次數和前臺進程進入log file sync等待。在進行PL/SQL處理期間,不停的查看等待事件,後臺看不到任何的log file sync等待。還有就是統計資料裏顯示了會話總共向lgwr發送了6次message sent請求(請求寫日誌),lgwr也接受到了6次message recived信息,並且寫了6次(log file parallel write)。你可能會問,到底多久,會話發送一次寫請求?每次前臺進程給LGWR發送寫請求前,會去持有redo writing latch,然後檢查lgwr是不是已經在處理寫請求了,如果lgwr已經在寫了,前臺進程不會向LGWR發送請求,也不會等待log fil sync,直接繼續完成後續的操作,如果lgwr沒在寫,前臺進程通知lgwr去寫,但是不會等待log file sycn,還是繼續完成後續的操作,只有在PL/SQL結束的時候,才會最終等待一次log file sync。因此如果你的磁盤寫的速率足夠快,那麽lgwr就會被post的次數越多,成正比的關系。還有如果你的cpu足夠強,那麽PL/SQL塊loop的時間就足夠小,時間小了,那麽lgwr被post的次數也就少了,成反比的關系(在磁盤寫速率一定的情況下)。
值得註意的是,如果PL/SQL裏包含了DBLINK,那麽就會使用傳統的提交方式,不會產生出這樣的“異常”。
最後提醒一句:雖然PL/SQL只有在結束的時候才會等待lgwr寫完成,產生log file sync等待,但是不要認為,在PL/SQL運行過程中,實例crash掉,此次PL/SQL處理的所有事務就會丟失,不是這樣的,只是丟失部分,pl/sql在運行過程中,會話是一直檢查lgwr是不是在工作的,如果沒在工作,就發送寫請求給lgwr的(message sent),lgwr接收到寫請求後,就要寫日誌,只要是被寫進了日誌文件的事務就是可恢復的。也就是說,雖然前臺沒有等待log file sync,但是後臺其實一直是在忙著處理你的事務日誌的。

發現問題的手段
方式一:從awr裏去發現,依據avg wait(ms)去判斷系統的log file sync和log file parallel write是否存在問題。
技術分享
方式二:通過moats工具去診斷當前數據庫的top wait有哪些,是否有log file sync、log file parallel write,工具下載地址:http://www.oracle-developer.net/utilities.php。
方式三:通過lewis的snap_events腳本,獲得系統級別等待事件的等待次數、平均等待時間。
rem execute snap_events.start_snap
rem execute snap_events.end_snap

方式四:通過tanel poder的snap腳本采樣lgwr後臺進程的等待事件分布以及lgwr進程相關的統計信息。




  1. SQL> @snapper out 1 10 1096
  2. -- Session Snapper v2.01 by Tanel Poder ( http://www.tanelpoder.com )
  3. ---------------------------------------------------------------------------------
  4. SID, USERNAME , TYPE, STATISTIC , DELTA, HDELTA/SEC, %TIME, GRAPH
  5. ---------------------------------------------------------------------------------
  6. 1096, (LGWR) , STAT, messages sent , 12 , 12,
  7. 1096, (LGWR) , STAT, messages received , 10 , 10,
  8. 1096, (LGWR) , STAT, background timeouts , 1 , 1,
  9. 1096, (LGWR) , STAT, physical write total IO requests , 40, 40,
  10. 1096, (LGWR) , STAT, physical write total multi block request, 38, 38,
  11. 1096, (LGWR) , STAT, physical write total bytes, 2884608 , 2.88M,
  12. 1096, (LGWR) , STAT, calls to kcmgcs , 20 , 20,
  13. 1096, (LGWR) , STAT, redo wastage , 4548 , 4.55k,
  14. 1096, (LGWR) , STAT, redo writes , 10 , 10,
  15. 1096, (LGWR) , STAT, redo blocks written , 2817 , 2.82k,
  16. 1096, (LGWR) , STAT, redo write time , 25 , 25,
  17. 1096, (LGWR) , WAIT, LGWR wait on LNS , 1040575 , 1.04s, 104.1%, |@@@@@@@@@@|
  18. 1096, (LGWR) , WAIT, log file parallel write , 273837 , 273.84ms, 27.4%,|@@@ |
  19. 1096, (LGWR) , WAIT, events in waitclass Other , 1035172 , 1.04s , 103.5%,|@@@@@@@@@@|
  20. -- End of snap 1, end=2010-03-23 12:46:04, seconds=1
復制代碼





相關的等待事件
1)log file sync(前臺進程的等待事件)
2)log file parallel write(後臺進程lgwr的等待事件)
3)log buffer space
lgwr刷新太慢可能會導致這個問題,導致lgwr刷新慢也有幾種情況
1.IO子系統太慢
2.lgwr不能獲得足夠的cpu資源
3.遭遇了大事務(expdp,insert /*+ append */ as ,imp,create as )
也可能是log buffer設置的太小了,不過在現在已經不太可能。默認的尺寸已經很大了。
4)log file single write
這個等待產生的原因是對日誌文件頭塊的讀寫。一般在如下情況下會產生:
1)日誌切換
2)歸檔


log file sync與buffer busy waits

事物在進行提交的時候,對事物修改的,還在內存裏的塊做commit cleanout,其實主要就是設置ITL槽位裏的commit scn,不會去清楚lb信息。ORACLE在進行commit cleanout期間,會獲取相關buffer的buffer pin,而且是排他模式獲取,這個pin直到lgwr把日誌刷入到磁盤才釋放,如果在此期間,有進程對相關的buffer進行select/update/insert就會造成buffer busy waits。因此如果你的系統log file sync指標很高,也可能會導致一定程度的buffer busy waits等待事件。

來自白大師(白鱔)對log file sync等待事件優化的總結,供各位puber們學習參考:

一、  log file sync平均等待事件時間超過7ms,如果等待時間過長,說明log write每次寫入的時間過長,如果能夠優化redo日誌文件存儲,使之存放在更快的磁盤上,就可以減少這個等待事件的單次等待時間。(RAID 5--> RAID 10)
 當無法通過優化redo日誌的I/O性能來解決問題,或者優化了redo日誌的I/O性能後還是無法達到我們的預期,那麽該如何處理呢?


二、 有經驗的DBA可能會建議加大日誌緩沖區(log buffer)。提到加大日誌緩沖區,可能有些朋友就會感到疑惑,redo日誌文件寫等待時間長怎麽會和日誌緩存沖區直接關聯起來呢?實際上這個問題解釋 起來一點也不難,如果數據文件的I/O性能有問題,平均單塊讀的等待時間偏長,那麽通過加大db cache來減少I/O總次數,從而達到優化I/O的效果。加大日誌緩存區的原理也是一樣的,這樣可以使
日誌緩存中的存儲更多的redo日誌數據,從而減少由於redo日誌緩存區不足而產生lgwr寫操作的數量,使平均每次寫入redo日誌文件的redo字節數增加,從而減少redo的I/O次數,進而達到優化log file sync等待事件的目的。


 三、如果上述兩種方法都不行時,還有一種方法:就是減少提交的次數。如果提交過於頻繁,那麽無論怎麽優化都無法徹底解決問題。
 通過加大一次提交記錄的數量,減少提交批次,可以有效地減少log file sync等待時間。采用此方法就意味著需要對應進行較大的調整,甚至要對應用架構做出修改,這種修改的代價將十分巨大。
  
 四、還有一個方案可以優化log file sync事件,就是把部分經常提交的事務設置為異步提交。
  異步提交是10g版本引入的新特性,通過設置commit_write參數,可以控制異步提交。
  commit_write參數默認值是“immediate,wait”
可以設置為“immediate,nowait”來實現異步提交。
采用異步提交的系統需要做一些額外的校驗和處理,清理不一致的數據,重新插入剛才由於異步提交而丟失的數據。這就需要在應用層面進行一些特殊處理,建校驗 機制和錯誤數據處理機制。我們需要在應用層面進行一些特殊的設置。應該註意的是,那些特別重要的,後續無法重新完全補充的數據不適合使用這種方法
  


log file sync等待事件是十分關鍵的,我們在數據庫的日常維護中應該對此指標建立基線,如果這個指標有異常變化,一定要盡快分析並解決問題。一旦這個指標惡化, 可能導致系統性能急劇下降,甚至會導致短暫的掛起。去年,一個客戶的系統,平時log file sync的指標是2-3ms。在一次巡檢時老白發現該指標增長到了7ms, 當時巡檢報告中建議客戶關註這個指標,並盡快檢查存儲系統和操作系統,查出變慢的原因。客戶檢查了存儲,沒發現故障,於是就不了了之了。在下個月巡檢的時 候,發現該指標增長到了13ms,再次預警,依然沒有發現問題。隨後兩個月這個指標一直持續惡化,增長到了20多毫秒。由於前面幾個月的檢查工作沒有發現 問題,而目前系統也還是很正常的,所以客戶也沒有再去認真核查。終於有一天,系統突然掛起,5分鐘後才恢復正常。後來檢查原因,就是log file sync等待導致。根據我的建議,客戶從頭到尾檢查了一遍,最終發現LVM的一條鏈路存存閃斷現象,修復了鏈路後,一切都恢復正常了。
   
   通過上面的案例,我們要吸取教訓,如果log file sync指標有所惡化,一定要盡快排查問題的根源,如果log file sync的等待時間持續上升,那麽系統出現掛起的可能性也在增加。盡快找到問題的原因是勢在必行的。

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

來自蓋大師(eygle)對log file sync等待事件優化的總結,供各位puber們學習參考:

http://www.eygle.com/statspack/statspack14-LogFileSync.htm
 當一個用戶提交(commits)或者回滾(rollback),session的redo信息需要寫出到redo logfile中.
用戶進程將通知LGWR執行寫出操作,LGWR完成任務以後會通知用戶進程.
這個等待事件就是指用戶進程等待LGWR的寫完成通知.

對於回滾操作,該事件記錄從用戶發出rollback命令到回滾完成的時間.

如果該等待過多,可能說明LGWR的寫出效率低下,或者系統提交過於頻繁.
針對該問題,可以關註:
log file parallel write等待事件
user commits,user rollback等統計信息可以用於觀察提交或回滾次數

解決方案:
1.提高LGWR性能
盡量使用快速磁盤,不要把redo log file存放在raid 5的磁盤上
2.使用批量提交
3.適當使用NOLOGGING/UNRECOVERABLE等選項

可以通過如下公式計算平均redo寫大小:

avg.redo write size = (Redo block written/redo writes)*512 bytes

如果系統產生redo很多,而每次寫的較少,一般說明LGWR被過於頻繁的激活了.
可能導致過多的redo相關latch的競爭,而且Oracle可能無法有效的使用piggyback的功能.

我們從一個statspack中提取一些數據來研究一下這個問題.

我們看到,這裏log file sync和db file parallel write等待同時出現了.
顯然log file sync在等待db file parallel write的完成.

這裏磁盤IO肯定存在了瓶頸,實際用戶的redo和數據文件同時存放在Raid的磁盤上,存在性能問題.
需要調整.

由於過渡頻繁的提交,LGWR過度頻繁的激活,我們看到這裏出現了redo writing的latch競爭.
關於redo writing競爭你可以在steve的站點找到詳細的介紹:
http://www.ixora.com.au/notes/lgwr_latching.htm

Oracle Internals Notes
LGWR Latching

When LGWR wakes up, it first takes the redo writing latch to update the SGA variable that shows whether it is active. This prevents other Oracle processes from posting LGWR needlessly. LGWR then takes the redo allocation latch to determine how much redo might be available to write (subject to the release of the redo copy latches). If none, it takes the redo writing latch again to recordthat it is no longer active, before starting another rdbms ipc message wait.
If there is redo to write, LGWR then inspects the latch recovery areas for the redo copy latches (without taking the latches) to determine whether there are any incomplete copies into the log buffer. For incomplete copies above the sync RBA, LGWR just defers the writing of that block and subsequent log buffer blocks. For incomplete copies below the sync RBA, LGWR sleeps on a LGWR wait for redo copy wait event, and is posted when the required copy latches have been released. The time taken by LGWR to take the redo writing and redo allocation latches and to wait for the redo copy latches is accumulated in the redo writer latching time statistic.

(Prior to release 8i, foreground processes held the redo copy latches more briefly because they did not retain them for the application of the change vectors. Therefore, LGWR would instead attempt to assure itself that there were no ongoing copies into the log buffer by taking all the redo copy latches.)

After each redo write has completed, LGWR takes the redo allocation latch again in order to update the SGA variable containing the base disk block for the log buffer. This effectively frees the log buffer blocks that have just been written, so that they may be reused.

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

來自呂大師(vage)對log file sync等待事件優化的總結,供各位puber們學習參考:


1、Log File Sync是從提交開始到提交結束的時間。Log File Parallel Write是LGWR開始寫Redo File到Redo File結束的時間。明確了這一點,可以知道,Log file sync 包含了log file parallel write。所以,log file sync等待時間一出,必先看log file parallel write。如果log file sync平均等待時間(也可稱為提交響應時間)為20ms,log file parallel write為19ms,那麽問題就很明顯了,Redo file I/O緩慢,拖慢了提交的過程。

2、 Log File Sync的時間不止log file parallel write。服務器進程開始提交,到通知LGWR寫Redo,LGWR寫完Redo通知進程提交完畢,來回通知也是要消耗CPU的。除去來回通知 外,Commit還有增加SCN等等操作,如果log file sync和log file parallel write差距很大,證明I/O沒有問題,但有可能是CPU資源緊張,導致進程和LGWR來回通知或其他的需要CPU的操作,得不到足夠的CPU,因而產 生延遲。

這 種情況下要看一下CPU的占用率、Load,如果Load很高、CPU使用率也很高,哪就是由於CPU導致Log file sync響應時間加長。這種情況下,數據庫通常會有一些並發癥,比如Latch/Mutex的競爭會比平常嚴重些,因為CPU緊張嗎,Latch /Mutex競爭一些會加巨的。

3、 log file sync和log file parallel write相差很大,但CPU使用率也不高,這種情況比較少見,這就屬於疑難雜癥範疇了。I/O也很快,CPU也充足,log fie parallel write響應時間很短,但log file sync響應時間確很大。這是最難定位的情況,可以全面對比下Redo相關資料(v$sysstat中的資料)、Redo相關Latch的變化情況。
比 如,redo synch time的平均響應時間,不是每次redo synch time都有提交,但每次提交必有redo synch time。如果redo synch time向應快,而log file sync慢,則說明Lgwr和進程的互相通知階段出了問題。還有redo entries,這個Redo條目數,真正含意是進程向Log Buffer中寫Redo的次數。redo log space wait time、redo log space requests資料和Log Buffer Space等待事件也要關註下。Log Buffer的大小通常不會影響Log File Sync,但通過Log Buffer的變化,可以了解Redo量的變化。
關於Log Buffer對Log File Sync的影響,

在新IMU機制下,Redo數據先在共享池中,提交時傳到Log Buffer中,如果這時有等待,等待時間是Log Buffer Space。從Log Buffer到磁盤,等待事件才是log file sync。
老機制下也一樣,Log Buffer之前的等待是log buffer space,log buffer之後的等待才是log file sync。

4、控制文件I/O有可能影響log file sync。
此問題還沒來得及深入研究,只是以前在阿裏的數據庫中觀察到這一現象。

5、Log File Sycn和Buffer Busy Waits。
沒 有直接關系。是其他原因,比如Redo相關的Latch,導致了Log File Sync和Buffer Busy Waits同時出現。此時Log File Sync和Buffer Busy Waits都不是原兇,真正的原兇是Log Buffer訪問性能下降。

6、以同步模式向遠端DataGuard傳送Redo,也會導致Log File Sync。

Redo是Oracle重要的優化對象,DBWR的工作原理我已經破譯的差不多了,下一目標就是LGWR,可惜還沒來得及搞,以後有時間再為大家詳細總結。

oracle之 等待事件LOG FILE SYNC (awr)優化