Oracle優化03-Latch和等待
思維導圖

系列
Latch解讀
oracle-等待事件解讀
Latch概述
Latch造成的等待事件 和 Lock造成的阻塞 ,是兩個不同的概念,在性能優化上如果能區分開這兩個因素引起的性能問題,將極大的提高我們性能分析的判斷能力。
那什么是latch呢?
首先我們試想一個場景: 一個數據塊正在被在被一個會話從磁盤讀入內存中,請注意,是正在讀取中,此時另外一個會話正好也需要這個數據塊,那改怎么辦呢?
為了保持數據的一致性,正常的處理邏輯另一個會話需要等待這個數據塊被讀取到內存中 ,那么正在讀取數據塊的會話 如何 阻止其他會話繼續讀取這個數據塊呢? 方法是 它需要獲得一種類似鎖一樣的資源,這種資源在oracle中稱為Latch。
Latch是Oracle為了保護內存結構而發明的一種資源。
在Oracle復雜的內存結構中,比如在SGA中,各種數據被反復從磁盤讀取到內存,又被重新寫會到磁盤上,如果有并發的用戶做相同的事情,Oracle必須使用一種機制,來保證數據在讀取的時候,只能由一個會話來完成,這種保護機制就用到了Latch。
可以把Latch理解為一種輕量級的鎖,它不會造成阻塞,只會導致等待。
阻塞是一種系統設計上的問題,而等待是一種系統資源爭用的問題。
分清楚這兩個概念后,就能夠對系統性能下降時,做出客觀的判斷,比如當我們發現系統緩慢的原因是由于很多Latch爭用的時候,要考慮系統及數據庫自身設計上是否有問題,比如是否綁定變量,是否存在熱塊,數據存儲參數設計是否合理等因素。
導致Latch爭用而等待的原因很多,內存中很多資源都可能存在這爭用。下面介紹兩類最常見的latch爭用。
共享池中的latch爭用
共享池shared pool 中如果存在大量的SQL被反復解析,就會造成很大的latch爭用和長時間的等待, 最常見的現象就是沒有綁定變量。
最常見的幾種共享池里的Latch是:
Oracle Database 11g Enterprise Edition Release 11.2.0.4.0
SQL> select * from v$latchname a where a.NAME like 'library cache%'; LATCH# NAME HASH ---------- ------------------------ ---------- 337 library cache load lock 2952162927 SQL>
1
2
3
4
5
6
7
在分析系統性能時,如果看到有 library cache 這樣的 Latch 爭用,就可以斷定是共享池中出現了問題,這種問題基本是由 SQL 語句導致的,比如沒有綁定變量 或者一些存儲過程被反復分析。
數據緩沖池Latch爭用
訪問頻率非常高的數據塊被稱為熱塊( Hot Block),當很多用戶一起去訪問某幾個數據塊時,就會導致一些 Latch 爭用.
最常見的 latch 爭用有:
buffer busy waits
cache buffer chain
這兩個Latch的爭用分別發生在訪問數據塊的不同時刻。
Buffer busy waits 產生原因
當一個會話需要訪問一個數據塊,而這個數據塊正在被另一個用戶從磁盤讀取到內存中或者這個數據塊正在被另一個會話修改時,當前的會話就需要等待,就會產生一個 buffer busy waits 等待。
產生這些 Latch 爭用的直接原因是太多的會話去訪問相同的數據塊導致
熱塊
問題, 造成熱塊的原因可能是數據庫設置導致或者重復執行的 SQL 頻繁訪問一些相同的數據塊導致
Cache buffer chian 產生原因
當一個會話需要去訪問一個內存塊時,它首先要去一個像鏈表一樣的結構中去搜索這個數據塊是否在內存中,當會話訪問這個鏈表的時候需要獲得一個Latch,如果獲取失敗,將會產生 Latch cache buffer chain 等待,導致這個等待的原因是訪問相同的數據塊的會話太多或者這個列表太長(如果讀到內存中的數據太多,需要管理數據塊的 hash 列表就會很長,這樣會話掃描列表的時間就會增加,持有 chache buffer chain latch 的時間就會變長,其他會話獲得這個 Latch 的機會就會降低,等待就會增加)。
Latch 是簡單的、低層次的序列化技術,用以保護 SGA 中的共享數據結構,比如并發用戶列表和 buffer cache 里的 blocks 信息。一個服務器進程或后臺進程在開始操作或尋找一個共享數據結構之前必須獲得對應的 latch,在完成以后釋放 latch。
不必對 latch 本身進行優化,如果 latch 存在競爭,表明 SGA 的一部分正在經歷不正常的資源使用。
熱塊產生的原因
熱塊產生的原因不盡相同,按照數據塊的類型,可以分成一下幾種類型,不同熱塊類型處理的方式都是不同的。
( 1) 表數據塊
( 2) 索引數據塊
( 3) 索引根數據塊
( 4) 段頭數據塊
表數據塊
比如在 OLTP 系統中,對于一些小表,會給出某些數據塊被頻繁查詢或者修改的操作,這時候,這些被頻繁訪問的數據塊就會變成熱塊,導致內存中 Latch爭用。
處理方式:
如果出現這樣熱塊的情況,并且表不太大,一個方法是可以考慮將表數據分布在更多的數據塊上,減少數據塊被多數會話同時訪問的頻率。
可以通過一下命令將每個數據塊存放記錄的數量減少到最少:
Alter table tableName minimize records_per_block;
1
功能:當前表所有block中容納的最大行數,并會把這個數字記錄到數據字典,以后任何導致block行數超過這個數字的插入都會被拒絕
缺點:
我們把數據分布到更多的數據塊上,大大降低了一個數據塊被重復讀取的概率。 但是這種方法的
缺點很明顯,就是降低了數據的性能,在這種情況下,訪問相同的數據意味著需要讀取更多的數據塊,性能會有所降低。
索引數據塊
這樣的情況通常發生在一個 RAC 架構里,某個表的索引鍵值出現典型的“右傾”現象,
比如一個表的主鍵使用一個序列來生成鍵值,那么在這個主鍵在索引數據塊上的鍵值就是以一種順序遞增的方式排列的,比如: 1, 2, 3, 4,5….,由于這些鍵值分布得非常接近,當許多用戶在 RAC 的不同實例來向表中插入主鍵時,就會出現相同的索引數據塊在不同實例的內存中被調用,形成一種數據塊的爭用。
對于這種情況,使用反向索引可以緩解這種爭用。
反向索引是將從前的索引鍵值按照反向的方式排列,在正常的主鍵 B-Tree 引中,鍵值會按照大小的順序排列,比如: 1234,反向索引,鍵值就變成 4321.
原理:這樣,本來是放在相同的索引數據塊上的鍵值,現在分布在不同的數據塊上,這樣用戶在 RAC 不同的實例上插入的主鍵值因為分布在不同的數據塊上,所以不會導致熱塊的產生,這基本是反向索引被使用的唯一情況。
反向索引使用場合之所以如此受限制,是因為它丟棄了 B-Tree 索引的一個最重要的功能:
Index range scan
索引訪問方式中,這個方式最常見,但是反向索引卻不能使用這個功能,因為反向索引已經把鍵值的排列順序打亂,當按照鍵值順序查找一個范圍時,在反向索引中,由于鍵值被反向存儲,這些值已經不是連續存放的了。 所以 Index range scan 的方式在反向索引中沒有任何意義。
在反向索引中只能通過全表掃描或者全索引掃描的方式來實現。 這就是反向索引的一個非常嚴重的缺陷。
索引根數據塊
熱塊也可能發生在索引的根數據塊上。
在 B-Tree 索引里,當 Oracle 訪問一個索引鍵值時,首先訪問索引的根,然后是索引的分支,最后才是索引的葉塊。
索引的鍵值就是存儲在葉塊上面。
當索引的根,枝數據都集中在幾個數據塊上時,比如 D, G 所在的枝數據塊,
當用戶訪問的范圍從 A-F,都會訪問這個數據塊,如果很多用戶頻繁的訪問這個范圍的索引鍵值,有可能導致這個枝數據塊變成熱塊。
當出現這種現象時,可以考慮對索引做分區,以便于使用這些根,枝數據塊分布到不同的數據段(分區)上,減少數據塊的并行訪問的密度,從而避免由于索引根,枝數據塊太集中導致熱塊產生。
段頭數據塊
從 Oracle 9i 開始,引入了一個自動段管理的技術 ASSM( Automatic SegmentSpace Management: ASSM),它讓 Oracle 自動管理“ Free List”。 實際上在 ASSM里,已經沒有 Free List 這樣的結構,
Oracle 使用位圖方式來標記數據塊是否可用,這種數據塊的空間管理方式比用一個列表來管理效率更高。
對于 OLTP 系統,表的 DML 操作非常密集,對于這些表,使用 ASSM 方式來管理會比人工管理更加方便和準確,能有效的避免段頭變成熱塊。
對于 OLAP 系統,這個參數并沒有太大的實際意義,因為在這樣的數據庫中,很少有表發生頻繁的修改, OLAP 系統主要的工作是報表和海量數據的批量加載。
檢查 Latch 的相關 SQL
查看造成 LATCH BUFFER CACHE CHAINS 等待事件的熱塊
SELECT DISTINCT a.owner, a.segment_name FROM dba_extents a, (SELECT dbarfil, dbablk FROM x$bh WHERE hladdr IN (SELECT addr FROM (SELECT addr FROM v$latch_children ORDER BY sleeps DESC) WHERE ROWNUM < 20)) b WHERE a.RELATIVE_FNO = b.dbarfil AND a.BLOCK_ID <= b.dbablk AND a.block_id + a.blocks > b.dbablk;
1
2
3
4
5
6
7
8
9
10
11
x$bh 只有sys用戶有訪問權限
X$表是oracle數據庫運行的基礎,在數據庫啟動時由Oracle應用程序動態創建,是不允許sysdba之外的用戶直接訪問的,顯示授權不被允許。
http://www.itpub.net/thread-950606-1-1.html
非SYS用戶訪問x$表
1。
訪問具體做法如下:
第一步:create view v_ps$bh as select * from x$bh;
第二步:grant select on v_ps$bh to party2;
第三步:create public synonym v_ps$bh for v_ps$bh;
完成三步后就可以訪問x$bh了,如同自己的Object。
2、完成前面的兩步后,
select * from sys.v_ps$bh也可以的。
詢當前數據庫最繁忙的 Buffer, TCH(Touch)表示訪問次數越高,熱塊競爭問題就存在
SELECT * FROM (SELECT addr, ts#, file#, dbarfil, dbablk, tch FROM x$bh ORDER BY tch DESC) WHERE ROWNUM < 11;
1
2
3
4
5
查詢當前數據庫最繁忙的 Buffer,結合 dba_extents 查詢得到這些熱點Buffer 來自哪些對象
SELECT e.owner, e.segment_name, e.segment_type FROM dba_extents e, (SELECT * FROM (SELECT addr, ts#, file#, dbarfil, dbablk, tch FROM x$bh ORDER BY tch DESC) WHERE ROWNUM < 11) b WHERE e.relative_fno = b.dbarfil AND e.block_id <= b.dbablk AND e.block_id + e.blocks > b.dbablk;
1
2
3
4
5
6
7
8
9
10
11
如果在 Top 5 中發現 latch free 熱點塊事件時,可以從 V$latch_children中查詢具體的子 Latch 信息
SELECT * FROM (SELECT addr, child#, gets, misses, sleeps, immediate_gets igets, immediate_misses imiss, spin_gets sgets FROM v$latch_children WHERE NAME = 'cache buffers chains' ORDER BY sleeps DESC) WHERE ROWNUM < 11;
1
2
3
4
5
6
7
8
9
10
11
12
13
14
獲取當前持有最熱點數據塊的 Latch 和 buffer 信息
SELECT b.addr, a.ts#, a.dbarfil, a.dbablk, a.tch, b.gets, b.misses, b.sleeps FROM (SELECT * FROM (SELECT addr, ts#, file#, dbarfil, dbablk, tch, hladdr FROM x$bh ORDER BY tch DESC) WHERE ROWNUM < 11) a, (SELECT addr, gets, misses, sleeps FROM v$latch_children WHERE NAME = 'cache buffers chains') b WHERE a.hladdr = b.addr;
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
利用前面的 SQL 可以找到這些熱點 Buffer 的對象信息
SELECT distinct e.owner, e.segment_name, e.segment_type FROM dba_extents e, (SELECT * FROM (SELECT addr, ts#, file#, dbarfil, dbablk, tch FROM x$bh ORDER BY tch DESC) WHERE ROWNUM < 11) b WHERE e.relative_fno = b.dbarfil AND e.block_id <= b.dbablk AND e.block_id + e.blocks > b.dbablk;
1
2
3
4
5
6
7
8
9
10
結合 SQL 視圖可以找到操作這些對象的相關 SQL,然后通過優化 SQL減少數據的訪問,或者優化某些容易引起爭用的操作(如 connect by 等操作)來減少熱點塊競爭
SELECT /*+ rule */ hash_value, sql_text FROM v$sqltext WHERE (hash_value, address) IN (SELECT a.hash_value, a.address FROM v$sqltext a, (SELECT DISTINCT a.owner, a.segment_name, a.segment_type FROM dba_extents a, (SELECT dbarfil, dbablk FROM (SELECT dbarfil, dbablk FROM x$bh ORDER BY tch DESC) WHERE ROWNUM < 11) b WHERE a.relative_fno = b.dbarfil AND a.block_id <= b.dbablk AND a.block_id + a.blocks > b.dbablk) b WHERE a.sql_text LIKE '%' || b.segment_name || '%' AND b.segment_type = 'TABLE') ORDER BY hash_value, address, piece;
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
Oracle SQL
版權聲明:本文內容由網絡用戶投稿,版權歸原作者所有,本站不擁有其著作權,亦不承擔相應法律責任。如果您發現本站中有涉嫌抄襲或描述失實的內容,請聯系我們jiasou666@gmail.com 處理,核實后本網站將在24小時內刪除侵權內容。
版權聲明:本文內容由網絡用戶投稿,版權歸原作者所有,本站不擁有其著作權,亦不承擔相應法律責任。如果您發現本站中有涉嫌抄襲或描述失實的內容,請聯系我們jiasou666@gmail.com 處理,核實后本網站將在24小時內刪除侵權內容。