latch:cache buffers chains的最佳化思路

531968912發表於2016-07-04
    資料塊在buffer cache存放是以linked list方式存放的。當一個session想要訪問/修改buffer cache的block,首先需要透過hash演算法檢查該block是否存在於buffer cache中,檢查相同的SQL語句是否存在於library cache中也是透過hash演算法實現的。要判斷block是否存在於buffer cache中,就需要掃描linked list(此處都是序列的,不能併發),獲取block的資訊。而掃描linked list必須獲得一個latch,防止併發對linked list照成破壞,如果未能獲得該latch,就會在資料庫中標記一個latch: cache buffers chains這個等待事件。如果該block存在於buffer cache中就不需要物理讀,如果不存在,就需要從磁碟讀取該block到buffer cache中。為了能夠讀取,並修改該block,我們就需要pin住該block,防止併發對於該block造成破壞,所以如果別的session不能獲得pin,同時會標記一個buffer busy waits等待事件。
一般產生CACHE BUFFERS CHAINS的原因有幾個方面:1、buffer cache太少(也說明SQL語句效率低);2、熱塊掙用。(從oracle9i開始,對latch:cache buffer chains支援只讀共享訪問,這可以減少部分爭用,但並不能完全消除爭用。)
一、buffer cache太少(也說明SQL語句效率低)
應用程式執行多個相同的低效率SQL語句併發會話,這些SQL語句都設法得到相同的資料集。較多的邏輯讀意味著較多的latch get操作,從而增加了鎖存器爭用。多個程式同時掃描大範圍的索引或表時,可能廣泛地發生cache buffers chains 鎖存器爭用。每次執行都帶有高 BUFFER_GETS(邏輯讀取)的SQL語句是主要的原因。
1、檢視當前的等待事件 ( latch: cache buffers chains)
SQL> select event, count(*) from v$session
 where wait_class <> 'Idle' group by event order by 2;
2、檢視 latch: cache buffers chains事件相關的會話資訊
SQL> select sid,username,machine,program,p1raw,sql_id,logon_time,last_call_et from v$session where event='latch: cache buffers chains';
二、熱塊掙用
當多個會話重複訪問一個或多個由同一個子cache buffers chains鎖存器保護的塊時,就會產生熱塊掙用。當多個會話爭用cache buffers chains鎖存器時,找出是否有熱塊的最好的方法是檢查latch free等待事件的P1RAW引數值。
判斷熱塊掙用的另一種方法是從 v$session_wait 檢視獲得鎖存器地址後進行比較。v$session_wait的P1RAW就相當於子鎖存器地址,若從 v$session_wait 檢視獲得的鎖存器地址過多重複出現,就意味著對相應鎖存器發生次數偏多,此時可解釋為熱快引起的爭用。如果會話正在相同的鎖存器地址上等待,就是熱塊。
SQL> select sid,p1raw,p2,p3,seconds_in_wait,wait_time,state from v$session_wait
where event='latch: cache buffers chains' order by 3,2;
檢視熱塊的物件:
根據TCH值確認熱塊。注意塊從LRU列表的冷端移動到熱端時,TCH值將重置為0,所以判斷的時候,要注意TCH為0的塊不一定是冷塊。
使用P1RAW=00000300DA316800為例子進行關聯熱快物件。
SQL> select a.hladdr,a.file#,a.dbablk,a.tch,a.obj,b.object_name from x$bh a, dba_objects b
where (a.obj = b.object_id or a.obj = b.data_object_id) and a.hladdr = '00000300DA316800'
union select hladdr,file#,dbablk,tch,obj,null from x$bh
where obj in (select obj from x$bh where hladdr = '00000300DA316800' minus select object_id from dba_objects minus select data_object_id from dba_objects) and hladdr = '00000300DA316800' order by 4;
若沒有關於SQL語句的資訊,也有方法間接判斷是熱塊引起的問題,還是低效SQL語句引起的問題。v$latch_children檢視中,比較子cache buffers chains鎖存器相應的 child#、gets、sleeps值, 以此判斷特定子鎖存器上使用的次數和爭用是否集中,利用以下語句,獲取sleeps次數高的子鎖存器。
SQL> select * from (select addr, child#, gets, sleeps from v$latch_children where name = 'cache buffers chains' order by sleeps desc)
where rownum < =20;
當結果中sleeps的值傾斜較大的時候就說明是熱塊掙用。
根據sleeps較高的addr確定哪些塊是熱塊。
SQL> select hladdr,obj,(select object_name from dba_objects where (data_object_id is null and object_id = x.obj) or data_object_id = x.obj and rownum = 1) as object_name,dbarfil,dbablk,tch from x$bh x where hladdr ='&p1raw' order by hladdr, obj;

==============End========================================================

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

相關文章