Oracle latch: cache buffers chains
buffer?cache深度分析之buffer?cache的優(yōu)化
?
buffer cache的等待事件
??? 與buffer cache相關(guān)的等待事件包括:latch free、buffer busy waits、free buffer waits。曾經(jīng)發(fā)生過的等待事件可以從v$system_event(一個等待事件對應(yīng)一行記錄)和v$session_event(一個session一個等待事件對應(yīng)一行記錄)中看到。而當前系統(tǒng)正在經(jīng)歷的等待事件可以從v$session_wait看到。
latch free等待
???????等待事件“l(fā)atch free”中與buffer cache有關(guān)的有兩類:cache buffers chains latch和cache buffers lru chain latch。在理解了上面所描述的有關(guān)buffer cache的內(nèi)部管理機制以后,就應(yīng)該很容易理解這兩個latch產(chǎn)生的原因。
??? 對于buffer cache中的每個hash chain鏈表來說,都會有一個名為cache buffers chains latch的latch來保護對hash chain的并發(fā)操作,這種latch通常也叫作hash latch或CBC latch。數(shù)據(jù)庫中會有很多的cache buffers chains latch,每個latch都叫做child cache buffers chains latch。一個child cache buffers chains latch會管理多個hash chain。前面我們知道,hash chain的數(shù)量由一個隱藏參數(shù):_db_block_hash_buckets決定。同樣也有一個隱藏參數(shù):_db_block_hash_latches來決定有多少個cache buffers chains latch來管理這些hash chain。該參數(shù)的缺省值由buffer cache中所含有的內(nèi)存數(shù)據(jù)塊的多少決定,當內(nèi)存數(shù)據(jù)塊的數(shù)量
???? ?少于2052個時,_db_block_hash_latches = power(2,trunc(log(2, 內(nèi)存塊數(shù)量 - 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語句來確定當前系統(tǒng)的cache buffers chains latch的數(shù)量。
?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的數(shù)量以后,我們只需要用hash chain的數(shù)量除以latch的數(shù)量以后,就可以算出每個latch管理多少個hash chain了。我們將下面7532除以1024,就可以知道,當前的系統(tǒng)中,每個latch大概對應(yīng)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
?
??? 當數(shù)據(jù)庫在hash chain搜索需要的數(shù)據(jù)塊時,必須先獲得cache buffers chains latch。然后在掃描hash chain的過程中會一直持有該latch,直到找到所要的數(shù)據(jù)塊才會釋放該latch。當有進程一直在掃描某條hash chain,而其他進程也要掃描相同的hash chain時,其他進程就必須等待類型為cache buffers chains latch的latch free等待事件。
??? 不夠優(yōu)化的SQL語句是導(dǎo)致cache buffers chains latch的主要原因。如果SQL語句需要訪問過多的內(nèi)存數(shù)據(jù)塊,那么必然會持有l(wèi)atch很長時間。找出邏輯讀特別大的sql語句進行調(diào)整。v$sqlarea里那些buffer_gets/executions為較大值的SQL語句就是那些需要調(diào)整的SQL語句。這種方式不是很有針對性,比較盲目。網(wǎng)上曾經(jīng)有人提供了一個比較有針對性的、查找這種引起較為嚴重的cache buffers chains latch的SQL語句的方式,其原理是根據(jù)latch的地址,到x$bh中找對應(yīng)的buffer header,x$bh的hladdr表示該buffer header所對應(yīng)的latch地址。然后根據(jù)buffer header可以找到所對應(yīng)的表的名稱。最后可以到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,就是熱點數(shù)據(jù)塊問題。這是指多個session重復(fù)訪問一個或多個被同一個child cache buffers chains latch保護的內(nèi)存數(shù)據(jù)塊。這主要是應(yīng)用程序的問題。大多數(shù)情況下,單純增加child cache buffers chains latches的個數(shù)對提高性能沒有作用。這是因為內(nèi)存數(shù)據(jù)塊是根據(jù)數(shù)據(jù)塊地址以及hash chain的個數(shù)來進行hash運算從而得到具體的hash chain的,而不是根據(jù)child cache buffers chains latches的個數(shù)。如果數(shù)據(jù)塊的地址以及hash chain的個數(shù)保持一致,那么熱點塊仍然很有可能會被hash到同一個child cache buffers chains latch上。可以通過v$session_wait的p1raw字段來判斷l(xiāng)atch free等待事件是否是由于出現(xiàn)了熱點塊。如果p1raw保持一致,那么說明session在等待同一個latch地址,系統(tǒng)存在熱點塊。當然也可以通過x$bh的tch來判斷是否出現(xiàn)了熱點塊,該值越高則數(shù)據(jù)塊越熱。
?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
?
接下來,我們就可以根據(jù)p1raw的值去找到所對應(yīng)的內(nèi)存數(shù)據(jù)塊以及對應(yīng)的表的名稱了。
?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';
?
關(guān)于處理Latch的問題的一個重要的動態(tài)性能視圖請參考我另外一篇博客:Oracle X$BH
?
?
總結(jié)
以上是生活随笔為你收集整理的Oracle latch: cache buffers chains的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: Python 不完全LU分解
- 下一篇: 文件名批量修改操作