Oracle latch: cache buffers chains
buffer?cache深度分析之buffer?cache的優化
?
buffer cache的等待事件
??? 與buffer cache相關的等待事件包括:latch free、buffer busy waits、free buffer waits。曾經發生過的等待事件可以從v$system_event(一個等待事件對應一行記錄)和v$session_event(一個session一個等待事件對應一行記錄)中看到。而當前系統正在經歷的等待事件可以從v$session_wait看到。
latch free等待
???????等待事件“latch free”中與buffer cache有關的有兩類:cache buffers chains latch和cache buffers lru chain latch。在理解了上面所描述的有關buffer cache的內部管理機制以后,就應該很容易理解這兩個latch產生的原因。
??? 對于buffer cache中的每個hash chain鏈表來說,都會有一個名為cache buffers chains latch的latch來保護對hash chain的并發操作,這種latch通常也叫作hash latch或CBC latch。數據庫中會有很多的cache buffers chains latch,每個latch都叫做child cache buffers chains latch。一個child cache buffers chains latch會管理多個hash chain。前面我們知道,hash chain的數量由一個隱藏參數:_db_block_hash_buckets決定。同樣也有一個隱藏參數:_db_block_hash_latches來決定有多少個cache buffers chains latch來管理這些hash chain。該參數的缺省值由buffer cache中所含有的內存數據塊的多少決定,當內存數據塊的數量
???? ?少于2052個時,_db_block_hash_latches = power(2,trunc(log(2, 內存塊數量 - 4) - 1))
??? ?多于131075個時,_db_block_hash_latches = power(2,trunc(log(2, db_block_buffers - 4) - 6))
??? ?位于2052與131075 buffers之間,_db_block_hash_latches = 1024
可以使用下面的SQL語句來確定當前系統的cache buffers chains latch的數量。
?SQL>?select?count(distinct(hladdr)) from?x$bh; COUNT(DISTINCT(HLADDR)) ----------------------- ?1024?SQL>?select?count(*) from?v$latch_children where?name='cache buffers chains'; ?COUNT(*) ---------- ?1024
?
??? ?在知道了cache buffers chains latch的數量以后,我們只需要用hash chain的數量除以latch的數量以后,就可以算出每個latch管理多少個hash chain了。我們將下面7532除以1024,就可以知道,當前的系統中,每個latch大概對應8個hash chain。
?SQL>?select?x.ksppinm, y.ksppstvl, x.ksppdesc ?2?from?x$ksppi x , x$ksppcv y where?x.indx =?y.indx and?x.ksppinm like?'\_%'?escape?'\'??and?ksppinm like?'%_db_block_hash_buckets%'?; KSPPINM KSPPSTVL KSPPDESC ---------------------- -------- ------------------------------------- _db_block_hash_buckets 7523?Number?of?database?block hash buckets
?
??? 當數據庫在hash chain搜索需要的數據塊時,必須先獲得cache buffers chains latch。然后在掃描hash chain的過程中會一直持有該latch,直到找到所要的數據塊才會釋放該latch。當有進程一直在掃描某條hash chain,而其他進程也要掃描相同的hash chain時,其他進程就必須等待類型為cache buffers chains latch的latch free等待事件。
??? 不夠優化的SQL語句是導致cache buffers chains latch的主要原因。如果SQL語句需要訪問過多的內存數據塊,那么必然會持有latch很長時間。找出邏輯讀特別大的sql語句進行調整。v$sqlarea里那些buffer_gets/executions為較大值的SQL語句就是那些需要調整的SQL語句。這種方式不是很有針對性,比較盲目。網上曾經有人提供了一個比較有針對性的、查找這種引起較為嚴重的cache buffers chains latch的SQL語句的方式,其原理是根據latch的地址,到x$bh中找對應的buffer header,x$bh的hladdr表示該buffer header所對應的latch地址。然后根據buffer header可以找到所對應的表的名稱。最后可以到v$sqltext(也可以到stats$sqltext)中找到引用了這些表的SQL語句。我也列在這里。where條件中的rownum<10主要是為了不要返回太多的行,只要能夠處理掉前10個latch等待就能有很大改觀。
?select?/**//*+ rule */?s.sql_text from?x$bh a,dba_extents b, (select?*?from?(select?addr from?v$latch_children ?where?name =?'cache buffers chains'?order?by?sleeps desc) where?rownum<11) c, v$sqltext s where?a.hladdr =?c.addr ?and?a.dbarfil =?b.relative_fno ?and?a.dbablk between?b.block_id and?b.block_id +?b.blocks ?and?s.sql_text like?'%'||b.segment_name||'%'?and?b.segment_type='TABLE'?order?by?s.hash_value,s.address,s.piece /
?
??? 還有一個原因可能會引起cache buffers chains latch,就是熱點數據塊問題。這是指多個session重復訪問一個或多個被同一個child cache buffers chains latch保護的內存數據塊。這主要是應用程序的問題。大多數情況下,單純增加child cache buffers chains latches的個數對提高性能沒有作用。這是因為內存數據塊是根據數據塊地址以及hash chain的個數來進行hash運算從而得到具體的hash chain的,而不是根據child cache buffers chains latches的個數。如果數據塊的地址以及hash chain的個數保持一致,那么熱點塊仍然很有可能會被hash到同一個child cache buffers chains latch上。可以通過v$session_wait的p1raw字段來判斷latch free等待事件是否是由于出現了熱點塊。如果p1raw保持一致,那么說明session在等待同一個latch地址,系統存在熱點塊。當然也可以通過x$bh的tch來判斷是否出現了熱點塊,該值越高則數據塊越熱。
?SQL>?select?sid, p1raw, p2, p3, seconds_in_wait, wait_time, state ?from?v$session_wait ?where?event =?'latch free'??order?by?p2, p1raw; ?SID P1RAW P2 P3 SECONDS_IN_WAIT WAIT_TIME STATE ---- -------- --- --- --------------- ---------- ------------------ ?38?6666535C 13?1?1?2?WAITED KNOWN TIME ?42?6666535C 13?1?1?2?WAITED KNOWN TIME ?44?6666535C 13?3?1?4?WAITED KNOWN TIME ……………………… ?85?6666535C 13?3?1?12?WAITED KNOWN TIME ?214?6666535C 138?1?1?2?WAITED KNOWN TIME
?
接下來,我們就可以根據p1raw的值去找到所對應的內存數據塊以及對應的表的名稱了。
?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 =?'6666535C';
?
關于處理Latch的問題的一個重要的動態性能視圖請參考我另外一篇博客:Oracle X$BH
?
?
總結
以上是生活随笔為你收集整理的Oracle latch: cache buffers chains的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: Python 不完全LU分解
- 下一篇: 文件名批量修改操作