天天看點

Oracle優化03-Latch和等待

思維導圖

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>      

在分析系統性能時,如果看到有 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;      

功能:目前表所有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 通路一個索引鍵值時,首先通路索引的根,然後是索引的分支,最後才是索引的葉塊。

索引的鍵值就是存儲在葉塊上面。

Oracle優化03-Latch和等待

當索引的根,枝資料都集中在幾個資料塊上時,比如 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;      

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;      

查詢目前資料庫最繁忙的 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;      

如果在 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;      

擷取目前持有最熱點資料塊的 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;      

利用前面的 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;      

結合 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;      

繼續閱讀