深入理解 latch: cache buffers chains
事件背景:? ?
一個(gè)客戶的數(shù)據(jù)庫(kù)發(fā)生了宕機(jī)事件,查看了數(shù)據(jù)庫(kù)的awr報(bào)告,原來(lái)是由于出現(xiàn)大量的latch: cache buffers chains等待事件導(dǎo)致系統(tǒng)消耗量大量的CPU,最終導(dǎo)致系統(tǒng)hang住;
說(shuō)明:? ?
要理解latch: cache buffers chains并解決這個(gè)問(wèn)題,就需要深入的了解Buffer Cache及其原理。
1、Buffer Cache概述:? ?
Buffer Cache是SGA的一部分,Oracle利用Buffer Cache來(lái)管理data block,Buffer Cache的最終目的就是盡可能的減少磁盤I/O。Buffer Cache中主要有3大結(jié)構(gòu)用來(lái)管理Buffer Cache:Hash Bucket、Hash Chain List、LRU List;? ?
Hash Bucket & Hash Chain List?:Hash Bucket與Hash Chain List用來(lái)實(shí)現(xiàn)data block的快速定位。? ?
LRU List?:掛載有指向具體的free buffer, pinned buffer以及還沒(méi)有被移動(dòng)到?write list的dirty buffer?等信息。所謂的free buffer就是指沒(méi)有包含任何數(shù)據(jù)的buffer,所謂的pinned buffer,就是指當(dāng)前正在被訪問(wèn)的buffer。? ?
Write(Dirty)List?:掛載有指向具體的?dirty block的信息。所謂的dirty block,就是指在?buffer cache中被修改過(guò)但是還沒(méi)有被寫入到磁盤的block。
2、Hash Bucket的原理:? ?
如果所有的Buffer Cache中所有的Buffer都通過(guò)同一個(gè)結(jié)構(gòu)管理,當(dāng)需要確定某個(gè)Block在Buffer中是否存在時(shí),將需要遍歷整個(gè)結(jié)構(gòu),性能會(huì)相當(dāng)?shù)拖?#xff1b;? ?
為了提高效率,Oracle引入了Bucket的數(shù)據(jù)結(jié)構(gòu),Oracle把管理所有的Buffer通過(guò)一個(gè)內(nèi)部的Hash算法運(yùn)算后,存放到不同Hash Bucket中,這樣通過(guò)Hash Bucket進(jìn)行分割之后,眾多的Buffer被分布到一定數(shù)量的Bucket之中,當(dāng)用戶需要在Buffer中定位數(shù)據(jù)是否存在是,只需要通過(guò)同樣的算法獲得Hash值,然后到相應(yīng)的Bucket中查找少量的Buffer即可確定。每個(gè)Buffer存放的Bucket由Buffer的數(shù)據(jù)塊地址運(yùn)算決定;(這個(gè)算法從ORACLE官方得到的信息很少,可以用索引的知識(shí)去理解)Bucket內(nèi)部,通過(guò)Cache Buffer Chain將所有的Buffer通過(guò)Buffer Header信息聯(lián)系起來(lái);?
為了保護(hù)Bucket中的數(shù)據(jù),每次訪問(wèn)的時(shí)候都需要先在內(nèi)存中獲取latches后才能訪問(wèn),整個(gè)訪問(wèn)的結(jié)構(gòu)如圖:?
用戶內(nèi)存中讀數(shù)據(jù)的順序:
a)?對(duì)該Block運(yùn)用Hash算法,得到Hash值。
b)獲得獲得cache buffers chains latch
c)?到相應(yīng)的Hash Bucket中搜尋相應(yīng)Buffer Header
b)獲得cache buffers chains latch;
d)?如果找到相應(yīng)的Buffer Header,然后判斷該Buffer的狀態(tài),看是否需要構(gòu)造CR Block,或者Buffer處于pin的狀態(tài),最后讀取。e)?如果找不到,就從磁盤讀入到Buffer Cache中。
3、latch:cache buffers chains等待事件 ?? ?
在Oracle9i以前,如果其它用戶進(jìn)程已經(jīng)獲得了這個(gè)latch,那么新的進(jìn)程就必須等待,直到該用戶進(jìn)程搜索完畢(搜索完畢之后就會(huì)釋放該latch)。從Oracle9i開(kāi)始?cache buffers chains latch可以只讀共享,也就是說(shuō)用戶進(jìn)程A以只讀(select)的方式訪問(wèn)Block,這個(gè)時(shí)候獲得了該latch,同時(shí)用戶進(jìn)程B也以只讀的方式訪問(wèn)Block,那么這個(gè)時(shí)候由于是只讀的訪問(wèn),用戶進(jìn)程B也可以獲得該latch。但是,如果用戶進(jìn)程B要以獨(dú)占的方式訪問(wèn)Block,那么用戶進(jìn)程B就會(huì)等待用戶進(jìn)程A釋放該latch,這個(gè)時(shí)候Oracle就會(huì)對(duì)用戶進(jìn)程B標(biāo)記一個(gè)latch:cache buffers chains的等待事件。
4、latch:cache buffers chains出現(xiàn)的原因? ?
4.1?不夠優(yōu)化的SQL。? ?
大量邏輯讀的SQL語(yǔ)句就有可能產(chǎn)生非常嚴(yán)重的latch:cache buffers chains等待,因?yàn)槊看我L問(wèn)一個(gè)block,就需要獲得該latch,由于有大量的邏輯讀,那么就增加了latch:cache buffers chains爭(zhēng)用的機(jī)率。???對(duì)于正在運(yùn)行的SQL語(yǔ)句,產(chǎn)生非常嚴(yán)重的latch:cache buffers chains爭(zhēng)用,可以利用下面SQL查看執(zhí)行計(jì)劃,并設(shè)法優(yōu)化SQL語(yǔ)句。
select * from table(dbms_xplan.display_cursor('sql_id',sql_child_number));? ?
如果SQL已經(jīng)運(yùn)行完畢,我們就看AWR報(bào)表里面的SQL Statistics->SQL ordered by Gets->Gets per Exec,試圖優(yōu)化這些SQL。
4.2熱點(diǎn)塊爭(zhēng)用??
?1)查找數(shù)據(jù)庫(kù)是否存在latch的爭(zhēng)用
select sid,event,p1text,p1raw from v$session_wait where event='latch: cache buffers chains';? ?
2)下面查詢查出Top 5?的爭(zhēng)用的latch address。
select * from( select CHILD#,ADDR,GETS ,MISSES,SLEEPS from v$latch_children where name = 'cache buffers chains' and misses>0 and sleeps>0 order by 5 desc, 1, 2, 3) where rownum<6;?
3)然后利用下面查詢找出Hot block。????
?select?/*+?RULE?*/? ? ?? e.owner?||'.'||?e.segment_name??segment_name,? ? ?? e.extent_id??extent#,? ? ?? x.dbablk?-?e.block_id?+?1??block#,? ? ?? x.tch, /* sometimes tch=0,we need to see tim */x.tim ,l.child#???? from? ? ?? v$latch_children??l,? ? ?? x$bh??x,? ? ?? dba_extents??e???? where? ? ?? x.hladdr??=?'&ADDR'?and? ? ?? e.file_id?=?x.file#?and? ? ?? x.hladdr?=?l.addr?and? ? ?? x.dbablk?between?e.block_id?and?e.block_id?+?e.blocks?-1? ?? order?by?x.tch?desc?;? ? ?? e.owner?||'.'||?e.segment_name??segment_name,? ? ?? e.extent_id??extent#,? ? ?? x.dbablk?-?e.block_id?+?1??block#,? ? ?? x.tch, /* sometimes tch=0,we need to see tim */x.tim ,l.child#???? from? ? ?? v$latch_children??l,? ? ?? x$bh??x,? ? ?? dba_extents??e???? where? ? ?? x.hladdr??=?'&ADDR'?and? ? ?? e.file_id?=?x.file#?and? ? ?? x.hladdr?=?l.addr?and? ? ?? x.dbablk?between?e.block_id?and?e.block_id?+?e.blocks?-1? ?? order?by?x.tch?desc?;?
4.3?Hash Bucket太少? ?需要更改_db_block_hash_buckets隱含參數(shù)。其實(shí)在Oracle9i之后,我們基本上不會(huì)遇到這個(gè)問(wèn)題了,除非遇到Bug。所以這個(gè)是不推薦的,記住,在對(duì)Oracle的隱含參數(shù)做修改之前一定要咨詢Oracle Support。?
5、latch:cache buffers chains的模擬測(cè)試
5.1?創(chuàng)建表
SQL> create table john (no int,object_name varchar2(50));?
5.2??插入數(shù)據(jù)S
QL> declare i int;beginfor i in 1..5 loopinsert into john? select? rownum as no,object_name from dba_objects;end loop;end;/?
5.3?創(chuàng)建存儲(chǔ)過(guò)程SQL> create or replace procedure p_john isi int;icount int;beginfor i in 1..1000 loopselect count(*) into icount from john;end loop;end;/?
5.4?模擬20并發(fā)全表掃描
SQL> var job_no number;S
QL> beginfor idx in 1..20 loopdbms_job.submit(:job_no,'p_john;');commit;end loop ;end;/?
5.5查看爭(zhēng)用情況
SQL>?select sid,event,p1text,p1raw from v$session_wait where event='latch: cache buffers chains';
顯示存大量的latch等待;
?5.6 ?latch: cache buffers chains等待事件在awr報(bào)告中的特征??
?
總結(jié)以上的特征:
a)??占用大量的CPU資源;
b)??邏輯讀比正常情況要多很多;
c)??等待事件里面肯定有l(wèi)atch: cache buffers chains
d)??Latch的命中率一般在95%以下,嚴(yán)重的在90%以下;
6、latch:cache buffers chains的個(gè)人解決方法很多時(shí)候應(yīng)用的問(wèn)題,其實(shí)是由于SQL質(zhì)量導(dǎo)致的,很多DBA吐槽:DBA和開(kāi)發(fā)是不同的部門,所以要讓開(kāi)發(fā)配合起來(lái)進(jìn)行SQL調(diào)優(yōu)難度較大,可行性較小。對(duì)于這種觀點(diǎn)本人表示不贊同:當(dāng)系統(tǒng)出現(xiàn)大的問(wèn)題的時(shí)候,會(huì)導(dǎo)致系統(tǒng)性能下降,甚至宕機(jī),那么如果這個(gè)系統(tǒng)重要的話,那么DBA完全可以把問(wèn)題的原因及解決方法發(fā)送給開(kāi)發(fā)人員,并抄送公司領(lǐng)導(dǎo),并說(shuō)明原因及解決的方法,由于這個(gè)時(shí)候DBA是唯一知道問(wèn)題的根源及解決方法的,所以領(lǐng)導(dǎo)也會(huì)支持你的;另外:SQL調(diào)優(yōu)是最有效的調(diào)優(yōu)方法,建議DBA別從系統(tǒng)的角度去進(jìn)行處理,避免填了一個(gè)坑又冒出一個(gè)坑;
+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
本文作者:JOHN?
+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
?
來(lái)自 “ ITPUB博客 ” ,鏈接:http://blog.itpub.net/12679300/viewspace-1244578/,如需轉(zhuǎn)載,請(qǐng)注明出處,否則將追究法律責(zé)任
總結(jié)
以上是生活随笔為你收集整理的深入理解 latch: cache buffers chains的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
- 上一篇: 【C语言练习4】根据公式计算π的值,π=
- 下一篇: 一起学WEB HTML5 第1讲