buffer busy waits

非空閒等待之:buffer busy waits
事件參數說明:


ORACLE會話正在等待PIN住一個緩衝區,會話必須在讀取或修改緩衝區之前將該緩衝區PIN住。
在任何時侯只有一個進程可以PIN住一個緩衝區。
buffer busy waits表明讀/讀、讀/寫、寫/寫爭用。
根據P3中指明的原因碼有不同的處理方式。
現象描述:會話在SGA中讀取或修改緩衝區之前,必須要先獲取cahce buffers chains鎖存器(latch),獲取後然後遍歷這個緩衝區鏈,直到發現它需要的緩衝區頭。然後以共享方式或獨佔方式獲取該緩衝區鎖或緩衝區頭部的PIN,一旦緩衝區被PIN住,會話即釋放cache buffers chains鎖存器。如果無法獲得PIN,會話就在buffer busy waits等待事件上等待。
該事件只與SGA中緩衝區相關,與會話私有的PGA中執行的讀/寫操作無關。




處理該等待事件時主要注意以下四方面:
1) 該等待事件主要的原因碼是什麼?(參數P3)
2) buffer busy waits事件需要的塊類?(由P1即可找出等待塊的類列)
3) 緩衝區所屬的段(由P1和P2參數配合視圖v$extents即可找出等待塊的所屬段)
select s.segment_name, s.partition_name 
  from dba_extents s 
where <P2的值> between s.block_id and (s.block_id + s.blocks -1) and s.file_id = <P1的值>
4) 和buffer busy waits事件相關的SQL語句




雖然buffer busy waits事件的發生可能至少有十個不同的原因,但是代碼130和220是最常見的原因。基本上,小於200的代碼號意味着這種等待是和I/O有關的。


帶有原因碼130的數據塊(類#1)爭用
1) 等待集中在數據塊上,並且原因碼是130,則意味着多個會話併發請求相同的數據塊,但該數據塊並不在緩衝存儲器中,並且必須從磁盤讀取。
2) 當多個會話請求不在緩衝存儲器中的相同數據塊時,ORACLE可以聰明地防止每個會話進行相同的操作系統I/O調用。否則,這可能嚴重地增加系統I/O的數量,所以,ORACLE只允許一個會話執行實際的I/O,而其他的會話在buffer busy waits上等待塊,執行I/O的會話在db file sequential read或db file scattered read等待事件上等待。
3) 可在v$session視圖中檢查SESSION的註冊時間,並且等待事件db file sequential(scattered) read和buffer busy waits等待相同的文件號和塊號。
4) 解決方法:優化SQL語句,儘可能地減少邏輯讀和物理讀;




帶有原因碼220的數據塊(類#1)爭用
1) 等待集中在數據塊上,並且原因碼是220,則意味着多個會話同時在相同的對象上執行DML(相同塊中的不同行)。
2) 如果數據塊的尺寸較大(>=16K),則可能強化這種現象,因爲較大的塊一般在每個塊中包含更多的行。
3) 減少這種情況的等待的方法:減少併發;減少塊中行的數量;在另一個具有較小塊尺寸的表空間中重新構建對象。
4) 具體方法說明:
使用較大的PCTFREE重新構建表或索引;
使用alter table <table_name> minimize records_pre_block命令改變表以最小化每個塊的最小行數
從ORACLE9i開始,可以在另一個具有較小塊尺寸的表空間中移動或重新構建對象。
注:雖然這些方法可以最小化buffer busy waits問題,但它們無疑會增加全表掃描時間和磁盤空間利用率。




數據段頭(類#4)的爭用
1) 如果buffer busy waits的等待事件主要集中在數據段頭(即表或索引段頭,並且不是UNDO段頭)上,這意味着數據庫中一些表或索引有高段頭活動。
注:進程出於兩個主要原因訪問段頭,一是,獲得或修改FREELISTS信息;二是,爲了擴展高水位標記(HWM)。
2) 減少這種情況的等待的方法:
>> 對使用自由表進行段管理的表,增加確認對象的FREELISTS和FREELIST GROUPS(注:FREELIST GROUPS的增加也是必須的);
>> 確保FCTFREE和PCTUSED之間的間隙不是太小,從而可以最小化FREELIST的塊循環。
>> 下一區的尺寸不能太小,當區高速擴張時,建立的新區需要修改在段頭中區映射表。可以考慮將對象移動到合理的、統一尺寸的本地管理的表空間中。




撤銷段頭(類#17)的爭用
1) 如果buffer busy waits等待事件主要集中在撤銷段頭,這表明數據庫中的回滾段過少或者是它們的區尺寸太小,從而造成對段頭的頻繁更新。如果使用ORACLE9I的由數據庫系統管理UNDO段,就不需要處理這種問題,因爲ORACLE會根據需要增加額外的的UNDO段。
2) 可以創建並啓用私有回滾段,以減少每個回滾段的事務數量。需要修改init.ora文件中的ROLLBACK_SEGMENTS參數。
3) 如果使用公用回滾段可以減少初始化參數transactions_per_rollback_segment的值,ORACLE通過transactions/transactions_per_rollback_segment來獲取公有回滾段的最小數量。




撤銷塊的爭用(類#18)
1) 如果buffer busy waits等待事件主要集中在撤銷塊上,這表明有多個併發會話爲保證一致性讀同時查詢更新的數據。
2) 這是應用程序存在問題,當應用程序在不同時間內運行查詢和DML時,這種問題不會存在。


附註:
一、查看系統所有段的有關buffer busy waits事件的統計:
SELECT * 
  FROM v$segment_statistics s 
WHERE s.statistic_name = 'buffer busy waits' 
AND s.owner <> 'SYS'


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




案例一、(自己做記錄)




在數據庫中出現了大量的Buffer busy wait,通過語句進行SQL抓取
select sysdate ,a.SQL_TEXT,s.MACHINE
   from v$sqlarea a, v$session s
 where a.HASH_VALUE = s.SQL_HASH_VALUE
    and s.SID in (select sid
                    from v$session_wait w
                   where w.EVENT = 'buffer busy waits')








第三部分:故障分析
一個簡單的入庫語句爲什麼會造成這麼大的性能影響,那這些等待又是怎麼發生的呢?我們首先來看看。。什麼是Buffer busy wait Event
 
解釋:
buffer busy waits常常是由於很頻繁的insert ,需要重建,或者沒有充足的回滾段引起的


發生條件:
block正被讀入緩衝區或者緩衝區正被其他session使用, 當緩衝區以一種非共享方式或者如正在被讀入到緩衝時,
就會出現該等待.該值不應該大於1%
 
細想以後,發現還有個併發的可能的等待read by other session
因爲10G以前,把一個等待事件read by other session也劃入到了buffer busy waits裏,
read by other session的意思是,多個session併發請求相同的數據塊,但因該數據塊不在buffer_cache中而必須從磁盤讀取,
處理這種情況,oracle會只讓其中一個sesion進行磁盤讀取,
此時其它session等待塊從磁盤上讀取進buffer_cache而拋出read by other session等待事件。
10G以後,read by other session被單獨了出來,buffer busy waits變的純粹,就是上面我說的那種情況了。
 

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