第6 章、解釋與鎖有關的等待事件

紅葉DBA發表於2011-02-28

章、解釋與鎖有關的等待事件

Oracle 通過Latch Lock 序列化對SGA 資料結構和資料庫物件的訪問,這是ACID Atomicity 原子性、Consistency 一致性、Isolation 隔離性、Durability 永續性)中的I(隔離性),在這種情況下,為了完整性必須犧牲併發性。

多個程式競爭序列化資源通常表現為latch free enqueue buffer busy wait 等待事件。

1、   Latch free 等待事件:

l  關鍵思想:

1)         鎖存器只應用於SGA 中的記憶體結構,他們不會應用於資料庫物件,他們的存在是為了保護各種記憶體結構不會由於併發訪問而遭到破壞。

2)      Oracle 等待獲得鎖存器所採取的動作依賴於程式競爭的鎖存器型別。

3)      Oracle 10g 之前的Latch free 代表所有的鎖存器等待事件,10g 之後常見的鎖存器被單獨取出,具有單獨的等待事件。

l  鎖存器是簡單的鎖裝置,他們是由部分組成的記憶體元素:PID (程式ID )、記憶體地址、長度。

l  存在中型別的鎖存器:父鎖存器、子鎖存器和單獨的鎖存器,v$latch_parent 包含父鎖存器,v$latch_children 包含子鎖存器,v$latch 包含單獨的鎖存器和父、子鎖存器的合計統計。

l  在獲得鎖存器後,要修改受保護的資料之前,程式將恢復資訊寫到鎖存器恢復區中,以便PMON 知道在獲得鎖存器的程式死亡時需要清除什麼。

l  離開鎖存器的唯一方式是GET 成功,程式在Get 幾次嘗試中沒有獲得鎖存器時,就會通知PMON 檢查鎖存器,如果以前持有該鎖存器的程式死亡,那麼就由PMON 清除並釋放鎖存器。

l  除了依靠_spin_count 引數來修改spin 次數外,還可以單獨修改某個latch spin 次數:

1)         x$ksllclass (核心服務鎖定鎖存器類)中檢視每個鎖存器類的spin 值:

Select indx,spin,yield,waittime from x$ksllclass;

2)      v$latchname 檢視要修改的鎖存器的編號:

select latch# from v$latchname where name= cache buffer chains ;

3)      修改一個沒有使用過的latch 類,在init 檔案中新增:

_latch_class_1= 10000 

_latch_classes= latch#:1 

4)      檢視latch 所屬的類:select a.kslldnam,b.kslltnum,b.class_ksllt from x$kslld a,x$ksllt b where a.kslldadr=b.addr and b.class_ksllt>0;

l  V$system_event.total_waits 記錄了以願意等待模式沒有獲取到latch  的次數,此值應該和sleeps 的總和相等,但由於sleeps 統計只在get 操作完成後才統計,所以total_waits>=sleeps 

l  Shared pool 鎖存器和library cache 鎖存器

u  Oracle 9i 開始,有7shared pool 鎖存器保護每個shared pool,還可以通過_kghdsidx_count 來修改子共享池的數量。library cache 也有自己的鎖存器,其數量通常為大於cpu_count 的最小質數,可以通過_kgl_latch_count 引數修改。

u  過多的硬解析會導致shared pool library cache 中的鎖存器競爭,這通常和沒有使用繫結變數有關。

u  如果在不同模式中擁有相同的物件,那麼就有可能造成鎖存器的爭用,因為相同的SQL 中引用的物件的模式不同,那麼就具有不同的child_number Oracle SQL 解析匹配時,必須持續持有鎖存器,然後一一掃描匹配,消耗時間。

l  Cache buffer chains 鎖存器

u  Oracle 9i 開始,cache buffer chains 鎖存器可以只讀共享,這樣就可以減少一部分的爭用,但是無法消除爭用。

u  有兩個隱藏引數:_db_block_hash_buckets _db_block_hash_latches ,分別控制雜湊桶數量和雜湊鎖存器數量。

u  每個邏輯讀都需要一個latch get 和一個CPU latch get 的唯一方法是獲得鎖存器,在某一個時刻,只能有一個程式擁有cache buffer 鏈。所以SQL 優化過程中必須要減小SQL 語句的邏輯讀。

u  減少熱塊的主要思想是將熱塊雜湊到不同的cache buffers chains 鎖存器所覆蓋的儲存桶,方法有:

1)         通過rowid 刪除一些行,並重新插入。

2)      輸出表,使用較大的pctfree 並輸入表,這是以空間為代價的。

3)      最小化每個行中的記錄數,records_per_block 引數修改表。

4)      對於索引,可以使用較高的pctfree ,但這種方法可能增加索引的高度。

5)      考慮減少塊大小。

u  檢視每個雜湊鎖存器管理的塊數:Select hladdr,count(*) from x$bh group by hladdr having count(*)>10;

如果一個雜湊鏈中的塊數超過了10 個,就認為是長雜湊鏈。

l  Cache buffers lru chain 鎖存器

u  LRU LRUW CKPT-Q 連結串列也連線到緩衝區頭,LRU 儲存通常緩衝區,LRUW 包含髒緩衝區,二者是相互排斥的。他們統一稱為工作集(working set )。每個工作集有一個鎖存器保護,所以工作集的數量由cache buffers lru chain 數量決定。

u  x$kcbwds (核心高速緩衝區工作集描述符)檢視可以檢視工作集情況:

Select set_id,set_latch from x$kcbwds order by set_id;

也可以從v$latch_children 中查詢name= cache buffer lru chain 得到。

u  隱含引數_db_block_lru_latches 可以改變LRU chains 鎖存器的數量:預設是cpu_count ,如果db_write_processes>4 那麼就是db_write_processes * cpu_count 

l  Row cache objects 鎖存器

u  針對行快取記憶體的調整非常有限,可以從v$rowcache 中檢視每個資料字典的統計資訊。常見的解決方案是增大shared pool size 

2、Enqueue 等待事件:

l  排隊:用作動詞時,他表示將一個鎖請求放入佇列的動作;用作名詞時,表示一個特殊的鎖,例如TX 排隊。排隊資源是受排隊鎖影響的資料庫資源,可從v$resource x$ksqrs (核心服務排隊資源)中檢視,受隱含引數_enqueue_resources 控制,v$resource_limit 提供了利用率統計。

l  排隊鎖:從檢視v$enqueue_lock x$ksqeq (核心服務排隊物件)中檢視,受_enqueue_locks 控制,TX 鎖和TM 鎖可能不在此檢視中,因為Oracle 使用不同的結構來管理TX TM 排隊,可以從x$ktadm (核心事務訪問定義DML 鎖)中查詢,v$lock 則顯示了所有的鎖資訊。

l  Enqueue hash chains 鎖存器:雜湊儲存桶:排隊雜湊鏈=1 

l  Enqueue 鎖存器的數量預設等於cpu_count ,可以通過隱含引數_enqueue_hash_chain_latches 調整。排隊雜湊表的長度來源於sessions 初始化引數=sessions-10 *2+55 ,可以通過_enqueue_hash 引數調整。

l  轉儲排隊結構到一個追蹤檔案:

alter session set event  immediate trace name enqueue level 3 ;

l  enqueue 事件P1 引數包含了排隊的type mode 

select sid,event, chr(bitand(p1,-167777216)/16776215)|| chr(bitand(p1, 16711680)/65535) type,mod(p1,16) mode from v$session_wait where event= enqueue ;

l  程式可以獲得中模式的排隊鎖,編號從0~6 

0:無。

1:空鎖(Null

2:行共享鎖(Row-Share RS ),也稱為子共享鎖(SubShare lock SS 

3:行獨佔鎖(Row-Exclusive RX ),也稱為子獨佔鎖(SubExclusive lock SX 

4:共享鎖(Share 

5:共享行獨佔鎖(Share Row Exclusive SRX ),也稱為共享子獨佔鎖(Share-SubExclusive lock SSX 

6:獨佔鎖(Exclusive 

l   相容

     2 相容

     3 相容

     4相容

     5相容

     6相容

l  可以從v$enqueue_stat 檢視enqueue 等待事件的例項級統計資訊。

l  幾種常見的enqueue 等待:

1)         模式中的TX enqueue 等待:enq: TX - row lock contention

enq 此等待發生在一個事務嘗試修改被另一個事務鎖定的行時,

2)      模式中的TX enqueue 通常是有以下原因引起的:1ITL 不足;、唯一鍵實施、、位對映索引條目。

3)      模式中的TX enqueue 等待:enq: TX - allocate ITL entry

u  當一個塊中所有的ITL 都在使用,並且pctfree 中沒有空間分配新的ITL 時,就會有嚴重的ITL 爭用。9i 以後,每個表中至少ITL,即使dba_tables 中顯示一個也是個。

u  Oracle 9i 開始,Oracle 會跟蹤ITL 等待的數量並記錄在v$segment_statistics 檢視中,statistic_name= ITL waits 

4)      模式中的TX enqueue 等待:enq: TX - row lock contention

發生在多個會話併發的將相同的鍵值插入具有唯一索引的表中時。

5)      模式中的TX enqueue 等待:enq: TX - index contention

6)      ST enqueue 等待:ST 鎖的爭用表明有多個獲得會話在字典管理的表空間中執行空間的分配和釋放。

7)      模式中的TM enqueue 等待:通常是由於外來鍵未加索引引起的。

3、Buffer busy wait 等待事件:

l  關鍵思想:

1)         Oracle 必須在讀取或修改緩衝區內容之前,pin 住相關的塊,在同一時刻,只能有一個程式pin 住一個塊。

2)      Buffer busy waits 表明讀/讀、讀/寫、寫/寫爭用。

3)      P3 引數在10g 之前表示原因碼,在10g 之後表示塊類,原因碼中比較常見的是130 1013 )和220 1016 )。130 表示多個程式同時訪問一個不在緩衝區裡的塊,此時只有第一個程式呼叫系統IO ,剩餘的程式在此事件上等待;220 表示多個程式嘗試併發修改同一個塊中的不同行,但在同一時刻一個塊只能被一個程式pin 住。

l  檢視x$kcbwait 是檢視v$waitstat 的基檢視,

l  檢視x$kcnfwait 根據資料檔案來跟蹤buffer busy waits 等待,其中indx 表示file#

l  檢視x$kcbwds 通過保護LRU LRUW lru chain 鎖存器來跟蹤buffer busy waits 

l  檢視x$ksolsfts v$segment_statistics 檢視的基檢視,通過跟蹤段資訊來跟蹤buffer busy waits ,其中有一列fts_smtp 記錄了爭對特定段更新值(fts_staval )的最近時間。

l  在以上檢視中的buffer busy waits 的值可能存在不一致的情況,原因有:

1)         底層的記憶體結構不被保護,在記憶體結構的同步中破壞了計數。

2)      Oracle 核心在不同位置呼叫buffer busy waits ,有些位置並不是新增實際等待數量,而是固定新增一個大數字(如100 )。

3)      針對這些記憶體結構沒有一致讀取。

 

來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/24465008/viewspace-688093/,如需轉載,請註明出處,否則將追究法律責任。

相關文章