Latch free等待事件四(轉)

zhouwf0726發表於2019-03-24

n 儘量減每個塊中的記錄數。首先需要dump一些資料塊來分析現在每個塊中的記錄數。Dump出來的跟蹤檔案中,nrow就是塊中的記錄總數。然後exp表,再truncate表,在表中插入你想要在每個塊中儲存的條數的記錄,然後使用alter table table_name minimize records_per_block,再truncate表,最後imp回資料即可。

n 可以考慮減少塊的大小。從oracle9i開始,資料庫可以支援不同的塊大小。例如當前塊大小為16k,你可以將表及其索引移動塊大小為8k的表空間中。這也會對全表掃描造成負面影響。並且,多個塊大小也會使得管理更復雜。

另外,從oracle9iR2開始,也可以通過增加隱含引數_spin_count的值來解決熱點塊導致的cache buffers chains latch爭用。最後,也可以通過隱含引數_db_block_hash_buckets來增加hash bucket的數量,從oracle8i開始,一般不建議採用這種辦法,如果實在要用,請保證_db_block_hash_buckets的值為一個質數,否則,oracle也會自動採用大於你提供的值的最小的質數值。

Cache buffers chains latch爭用原因三 ―― 過長的hash chain

多個資料塊可能分配到同一個hash bucket上。這些塊組成一個連結串列(hash chain)。在一個大型系統中,一個hash bucket中可能有上百個資料塊。從一個hash chain連結串列中搜尋某個塊,需要獲得cache buffers chains latch,序列的進行。如果連結串列太長,使得latch持有時間相應增加,可能導致其他程式請求cache buffers chains latch失敗。

oracle8.0之前,由於hash latchhash buckethash chain之間是1:1:1的關係,很容易計算一個hash chain的長度,等於一個latch需要保護的資料塊數。通過下面的查詢可以知道一個hash chain上的資料塊數。一般而言,一個hash chain連結串列上超過10個資料塊就認為太長了。

Select hladdr, count(*)
from x$bh
group by hladdr
order by 2;

oracle8i起,hash latchhash bucket之間的關係變成了1:m。這樣就很難計算某個hash chain具體的長度了。只能計算一個hash latch需要保護多少個資料塊。而一個hash latch可能同時保護多個hash chain連結串列。上面的那個查詢的結果變成了每個hash latch需要保護的資料塊數。在你判斷一個hash latch保護的資料塊是否過量之前,需要先得到hash latchhash bucket的比值。在下面的例子中,每個hash latch保護125hash chain。如果你想要每個hash chain上不超過10個資料塊,則每個hash latch保護的資料塊不能超過1250個。通過隱含引數_db_block_hash_buckets可以增加hash bucket的數目,這樣可以減少每個hash chain上的資料塊數(因為hash buckethash chain之間是1:1的關係)。從oracle8i開始,一般不建議這麼做。

_db_block_hash_buckets = 128021
_db_block_hash_latches = 1024
ratio = 128021 / 1024 = 125

Cache buffers lru chain latch

除了hash chain,緩衝頭同樣組成一個列表,這個列表指向其他的列表比如lrulruwckpt-qLrulruw列表並不是什麼新東西,他們是資料緩衝區中最早的兩個連結串列。Lru列表包含了不同狀態的快取塊,而lruw就是俗稱的“髒表”,只包含髒資料塊。Lrulruw列表是互斥的,他們合稱一個工作集(a working set)。每個工作集由一個cache buffers lru chain latch保護。換句話說,資料緩衝區中工作集的個數是由cache buffers lru chain latch的個數決定的。通過內部檢視x$kcbwds (kernel cache buffer working sets descriptors)可以知道工作集的個數。我們注意到x$kcbwds set_latc的值就是v$latch_childrenaddr列。

lru + lruw = a working set

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

set_id set_latc
  
---------- --------
1 247e299c
2 247e2e68
3 247e3334
4 247e3800
5 247e3ccc
6 247e4198
7 247e4664
8 247e4b30

select addr
from v$latch_children
where name = ’cache buffers lru chain’
order by addr;

addr
--------
247e299c
247e2e68
247e3334
247e3800
247e3ccc
247e4198
247e4664
247e4b30

一般來講,當程式需要查詢可用的快取空間時,需要訪問lru列表。後臺程式DBWn則會將lruw列表中的乾淨塊移到lru列表中,也會將lru中的髒塊移到lruw列表中。在一個工作集中進行以上的任何操作都需要先獲得cache buffers lru chain latch

各個資料緩衝區中(包括不同塊大小的緩衝區,keep池和recycle池),每個緩衝區至少需要有一個cache buffers lru chain latch,而一個DBWn程式可能需要多個latch。否則,一個工作集就可能變得很長。在oracle9ioracle10g中,cache buffers lru chain latch的個數預設是cpu個數的4倍,如果,db_writer_processes大於4,則等於cpu的個數乘以db_writer_processes。可以通過隱含引數_db_block_lru_latches來調節cache buffers lru chain latch的個數。

Cache buffers laru cahin latch的爭用,主要表現為由於低效的sql語句導致資料緩衝區過度活躍。全表掃描和對某些選擇性較差的大索引的反覆掃描是造成cache buffers laru cahin latch爭用的主要原因。解決辦法是,查詢latch free等待事件中關於cache buffers lru chain latch相關的sql語句(在oracle10g中,已經變成一個獨立的cache buffers lru chain等待事件),優化這些sql,降低其物理讀和邏輯讀。

Row cache objects latch

Row cache objects latch用來保護資料字典緩衝區(row cache的名字主要是因為其中的資訊是按行儲存的,而不是按塊儲存)。程式在裝載、引用或者清除資料字典緩衝區中的物件時必須獲得該latch。在oracle8i之前,這是一個獨立latch。從oracle9i起,由於引入了多個子共享池的新特性,存在多個row cache objectslatchOracle10g中,該latch也有了一個獨立的等待事件:row cache objects

oracle7.0起,資料字典緩衝成為了共享池的一部分。而在7.0之前,每個資料字典物件都是由獨立的dc_*初始化引數控制。Oracle7.0的這個改變也意味著,不能再直接的調整資料字典緩衝,而只能通過調整shared_pool_size來間接的調整。V$rowcache檢視包含了每個資料字典物件的統計資訊。你可以通過下面的查詢發現最熱的資料字典物件。

Select cache#, type, parameter, gets, getmisses, modifications mod 
from v$rowcache
where gets > 0
order by gets;

cache# type parameter gets getmisses mod
------ ----------- ------------------ ---------- ---------- ------
7 subordinate dc_user_grants 1615488 75 0
2 parent dc_sequences 2119254 189754 100
15 parent dc_database_links 2268663 2 0
10 parent dc_usernames 7702353 46 0
8 parent dc_objects 11280602 12719 400
7 parent dc_users 81128420 78 0
16 parent dc_histogram_defs 182648396 51537 0
11 parent dc_object_ids 250841842 3939 75

對資料字典緩衝區的調節手段是有限的。最好的辦法是降低對前面的查詢結果中一些熱點資料字典物件的訪問。舉個例子,如果對某些sequence訪問頻繁,可以將考慮將這些sequnce快取在記憶體中。包含多個基表連線或者基於檢視的檢視可能導致該latch爭用。一般的解決辦法是增加shared_pool_size的值。


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

相關文章