Latch free等待事件一
Latch free等待事件的三個引數:p1-latch的地址;p2-latch編號;p3-請求次數。從oracle10g起,latch free不再包含所有的latch等待,有些latch等待可能表現為單獨的等待事件,這個後面有提到一些這樣的等待事件,一般情況下我們還是統稱為latch free等待事件。在處理latch free等待事件時,需要注意以下幾點:
n Latch只是用來保護sga中的記憶體結構。對資料庫中的物件的保護,使用的lock而不是latch。Oracle sga中有許多latch,用來保護sga中各種記憶體結構不會因為併發訪問而損壞。
n 等待latch的是oracle會話。不同的latch型別會導致會話採取不同的策略。
n 在oracle9i(包括9i)之前,latch free等待事件包括了所有的latch等待,但從oracle10g起,latch被分成不同的種類,並且某些latch表現為獨立的等待事件。
什麼是latch
Latch是一種鎖機制。你應該已經熟悉latch的概念和用法,雖然可能你自己並沒有意識到。在日常的工作和交流中,latch都經常出現,比如你鎖門時,需要獲得一個latch;或者你坐到車裡,繫上安全帶,你就把自己放在一個latch的保護中了。
在oracle中,latch是一種輕量級的鎖。一般來說,latch由三種記憶體元素組成:pid(程式id),記憶體地址和記憶體長度。Latch保證對共享資料結構的排它性訪問,以此來保證記憶體結構的完整性不受到損壞。在多個會話同時修改或者檢視(inspect)sga中同一個記憶體結構時,必須序列化訪問以保證sga中資料結構的完整性。
Latch和lock的異同
Latch和lock有許多不同之處。下表列出了latch和lock之間的比較結果。
Latch | Lock | |
目的 | 只有一個目的:保證對記憶體結構的排他性訪問(從oracle9i開始,cache buffers chain latch可以允許只讀共享訪問) | 兩個目的:如果鎖模式是相容的,允許多個程式共享相同的資源;如果鎖模型是不相容的,保證對共享資源的排它性訪問。 |
適用場景 | 只能應用於sga中的資料結構,保護記憶體物件。Latch隻影響單次操作,而和事務無關。 | 保護資料庫物件,諸如表,資料塊和狀態物件等。由應用程式驅動,控制對資料庫中資料和後設資料的訪問。 Lock是事務性的。 |
獲取方式 | 兩種模式:willing-to-wait和no-wait | 六種模式:null, row share, row exclusive, share, share row exclusive和exclusive |
範圍 | 資訊都儲存在記憶體中,並且只在本例項可見――latch是例項級別的 | 資訊儲存在資料庫中,並且該資料庫的所有例項都可見――lock是資料庫級的 |
複雜度 | 使用簡單機器指令比如:test-and-set, compare-and-swap或其他簡單的cpu指令實現。由於cpu指令平臺相關,所以latch在不同的平臺的具體實現不一樣。 輕量級的。 | 需要上下文切換(context siwtch),使用一系列指令實現。 重量級的。 |
持續事件 | 非常短暫(通常是微妙級的) | 通常在整個事務中都持有。 |
排隊機制 | 當一個程式獲取latch失敗,轉入睡眠狀態時,他的請求不需要按順序排隊(一個例外情況:latch wait list latch需要排隊)。 | 當一個程式獲取lock失敗,它的請求會進入一個佇列,除非指定nowait。 |
死鎖 | Latch的實現方式不會產生死鎖(不排隊) | Lock的排隊機制可能導致死鎖。死鎖發生時會產生相應的跟蹤檔案。 |
Latch家族
Latch有三種:父latch,子latch和獨立latch。父latch和獨立latch在oracle的核心程式碼中固化,子latch則在例項啟動時創造。V$latch_parent和v$latch_children檢視分別包含父latch和子latch的統計資訊。而v$latch則包含獨立latch,父latch及其相應子latch的聚合統計資訊。
Latch的獲取
程式獲取latch有兩種模式:willing-to-wait和no_wait。No-wait模式只在少數latch中使用。透過no-wait模式獲取latch的統計資訊記錄在immediate_gets和immediate_misses列中,這些列在v$latch,v$latch_parent,v$latch_children檢視中都存在。一般來說,no-wait模式在第一次獲取一些有很多子latch的latch比如redo copy時使用。如果一個程式第一次獲取這些子latch中的任何一個失敗,它會立即使用no-wait模式詢問下一個。只有當採用no-wait模式試圖獲取所有的子latch都失敗以後,才會轉而採用willing-to-wait模式。
透過willing-to-wait模式獲取latch的統計資訊存放在gets和misses列中。每當一個程式用willing-to-wait模式去獲取一個latch時,gets都會增加。
如果程式在第一次請求latch時,latch可用,就會直接獲得該latch。在修改任何受到保護的資料結構之前,程式會將一些恢復資訊寫入到latch恢復區,這樣當獲得latch的程式發生異常時,pmon程式才能夠清理該程式持有的latch。
如果請求latch時,該latch不可用,程式就會在cpu中等待一小段時間(spin)然後重新請求latch。如果latch一直不可用,該過程(spin一段時間然後重新請求)會一直重複。重複的次數由隱含引數_spin_count決定,預設值2000。如果在請求_spin_count次之內獲得了latch,就對spin_gets和misses列各加一,否則,程式在v$session_wait中記錄latch free等待事件,然後釋放cpu,轉入睡眠狀態。睡眠一定時間後,程式被喚醒並重覆上面的過程,一直到獲得latch。在成功獲得latch後,才會更行sleep列得統計資訊。
由於程式只有在獲得latch後才會停止對latch得請求,如果某個持有latch的程式發生異常,其他請求該latch的程式該怎麼辦?豈不是要一直等待下去?不會的。當一個程式請求latch失敗一定次數後,它會請求pmon程式檢視該latch的持有者,如果持有程式異常,pmon就會清理該程式,釋放latch。
每個latch都有一個從0到13的優先順序編號。父latch和獨立latch的優先順序編號是在oracle核心程式碼中固定的。子latch是÷在例項啟動時建立,其優先順序編號從其父latch繼承。使用優先順序可以避免死鎖。
n 當一個程式請求no-wait模式的latch時,該latch的優先順序編號必須和它當前已經持有的latch的優先順序編號相同。
n 當一個程式請求willing-to-wait模式的latch時,該latch的優先順序編號必須比它當前已經持有的latch的優先順序編號要大。
短等待latch與長等待latch
大多數latch都是短等待latch,所以,程式請求latch時不會等待太長的時間。Oracle程式請求latch失敗而導致進入睡眠狀態,每次睡眠時間按雙指數佇列增長,比如睡眠時間可能像下面的佇列一樣:1,1,2,2,4,4,8,8,16,16,32,32,64,64(釐秒)……,最長的睡眠時間由隱含引數_max_ exponential_sleep,預設2秒。但是如果一個程式當前已經持有其他的latch,則最長睡眠時間會減少為_max_sleep_holding_latch,預設值4釐秒。這樣,如果一個程式已經持有latch,就不允許睡眠太長的時間,否則可能會使其他等待該程式所持有的latch的程式的等待時間過長。
有小部分latch屬於長等待latch,這意味著這些latch被可能長久持有。如果請求該latch的程式進入睡眠狀態,需要其他程式來喚醒,這會產生一個latch wait posting等待事件,該行為由隱含引數_latch_wait_posting控制。在oracle8i,只有2個長等待latch,如下面的示例sql(oracle9i和oracle10g有更多長等待latch)所示。_latch_wait_posting引數從oracle9i起已經廢棄,使用latch wait posting的latch的統計資訊被記錄在waiters_woken列中。
Select name, immediate_gets, immediate_misses,
gets, misses, sleeps, waiters_woken
From v$latch
Where waiters_woken > 0;
immediate immediate waiters
Name gets misses gets misses sleeps woken
------------------------ --------------- -------------------- ----------------- ------------- --------------- ---------------
Shared pool 0 0 18464156 3124 1032 485
Library cache 85508 124 1564400540 4334362 1516400 690419
Latch分類
從oracle9iR2開始,latch可以被分成不同的型別,每一類latch都可以有不同的_spin_count值。在早期版本中,如果改變_spin_count值,會對系統中所有的latch造成影響。這樣可能會增加cpu的負擔,而latch分類則正是為解決這個問題而引入的。例如,如果cache buffers chains latch的sleep次數很多,而且cpu資源充足,我們就可以將cache buffer chains latch所在的分類的_spin_count的值調高。高_spin_count值可以降低sleeps和misses的次數,代價是花費更多cpu時間。內部檢視x$ksllclass (kernel serverice lock latches class)包含了latch的所有八種型別的資訊。其中indx列就是latch型別編號。
Select indx, spin, yield, waittime
from x$ksllclass;
indx spin yield waittime
---------- ---------- ---------- ----------
0 20000 0 1
1 20000 0 1
2 20000 0 1
3 20000 0 1
4 20000 0 1
5 20000 0 1
6 20000 0 1
7 20000 0 1
8 rows selected.
x$ksllclass中的每行記錄都和一個隱藏引數_latch_class_n關聯,透過這些隱含引數,你可以改變相應的_spin_count,yield和waittime的值(x$檢視不能由使用者手動更新)。例如,latch型別0由引數_latch_class_0控制,latch型別1由引數_latch_class_1控制。如果你想將cache buffers chains latch的_spin_count值改成10,000,首先你需要知道latch的編號,透過以下查詢可以獲得
Select latch#, name
From v$latchname
Where name = ’cache buffers chains’;
latch# name
---------- -------------------------------
97 cache buffers chains
然後,你需要修改init.ora中的下面2個引數:
_latch_class_1 = "10000"
_latch_classes = "97:1"
第一個引數_latch_class_1將型別1的spin_count值改為10,000;
第二個引數_latch_classes 將編號為97的latch分配到型別1。
再次查詢x$ksllclass,我們可以發現:
Select indx, spin, yield, waittime
From x$ksllclass;
indx spin yield waittime
---------- ---------- ---------- ----------
0 20000 0 1
1 10000 0 1
2 20000 0 1
3 20000 0 1
4 20000 0 1
5 20000 0 1
6 20000 0 1
7 20000 0 1
8 rows selected.
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;
Kslldnam kslltnum class_ksllt
------------------------- ---------- -----------
Process allocation 3 2
Cache buffers chains 97 1
注意:如果伺服器的cpu資源緊張,請不要增加_spin_count的值。當然,預設值2000是很久以前定下來的值,當時的cpu比現在的cpu要慢得多。
Latch free等待事件可以告訴我們什麼?
如果我們在v$session_wait中發現有latch free等待事件,就意味著,程式在請求一個willing_to_wait模式的latch,在重試了_spin_count次後還是沒有獲得latch,然後轉入睡眠狀態了。如果latch爭用嚴重,將會由於不斷的spin導致cpu資源緊張,從而增加系統響應時間。
V$system_event檢視的total_waits列記錄了程式獲取willing-to-wait模式latch失敗的次數。V$latch的sleeps列記錄了程式由於等待某個latch而進入睡眠狀態的次數。由於一個程式在_spin_count次嘗試請求latch失敗後會轉入睡眠狀態,total_waits列應該等於sleeps列的值的和,如以下sql所示。但是,某些時候,total_waits會比sleeps的和要大,這是因為,只有在程式獲得latch後才會更新total_waits的值,而不是每次請求latch失敗就更新。
Select a.total_waits, b.sum_of_sleeps
from (select total_waits from v$system_event where event = ’latch free’) a,
(select sum(sleeps) sum_of_sleeps from v$latch) b;
total_waits sum_of_sleeps
----------- -------------
414031680 414031680
由於latch free等待時間一般較短,所以在很少一段時間內,total_waits就可能變得非常大,這並不一定意味著系統有問題。只有當time_waited的值也非常顯著的時候,你才需要關注latch free等待事件。
Latch失敗區域(latch miss locations)
V$latch_misses檢視儲存了latch失敗在oracle核心程式碼中的區域資訊。這些資訊對於oracle support診斷latch等待事件有幫助。你可以透過以下查詢檢視位置資訊。Steve adams有篇非常棒的關於這方面的文章
Select location,
parent_name,
wtr_slp_count,
sleep_count,
longhold_count
from v$latch_misses
where sleep_count > 0
order by wtr_slp_count, location;
longhold
location parent_name wtr_slp_count sleep_count count
-------------------- -------------------- ------------- ----------- --------
. . .
Kglupc: child library cache 7879693 11869691 0
kghupr1 shared pool 8062331 5493370 0
kcbrls: kslbegin cache buffers chains 9776543 14043355 0
kqrpfl: not dirty row cache objects 15606317 14999100 0
kqrpre: find obj row cache objects 20359370 20969580 0
kglhdgn: child: library cache 23782557 9952093 0
kcbgtcr: fast path cache buffers chains 26729974 23166337 0
kglpnc: child library cache 27385354 7707204 0
Oracle10gR1中的latch
在Oracle10g之前,所有的latch等待都顯示為latch free等待事件。你可以透過latch free事件的p2引數和v$latch.latch#關聯或者透過10046事件來查詢某個程式爭用的是哪個latch。而在Oracle10g中,latch被分成許多獨立的等待。下面是oracle10gR1的latch一個列表:
Select name
from v$event_name
where name like ’latch%’
order by 1;
name
----------------------------------------------------------------
latch activity
latch free
latch: in memory undo latch
latch: kcl gc element parent latch
latch: mql tracking latch
latch: cache buffer handles
latch: cache buffers chains
latch: cache buffers lru chain
latch: checkpoint queue latch
latch: enqueue hash chains
latch: gcs resource hash
latch: ges resource hash list
latch: latch wait list
latch: library cache
latch: library cache lock
latch: library cache pin
latch: messages
latch: object queue header heap
latch: object queue header operation
latch: parallel query alloc buffer
latch: redo allocation
latch: redo copy
latch: redo writing
latch: row cache objects
latch: session allocation
latch: shared pool
latch: undo global data
latch: virtual circuit queues
28 rows selected.
來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/18921899/viewspace-1017391/,如需轉載,請註明出處,否則將追究法律責任。
相關文章
- 【分享】latch free等待事件(一)事件
- latch free等待事件事件
- Latch free等待事件(轉)事件
- Latch free等待事件三事件
- Latch free等待事件四事件
- Latch free等待事件二事件
- Latch free等待事件三(轉)事件
- Latch free等待事件四(轉)事件
- Latch free等待事件二(轉)事件
- latch free 等待事件說明事件
- latch free 等待事件說明(轉)事件
- latch free 等待事件的診斷語句事件
- latch等待事件彙總事件
- latch 相關等待事件事件
- latch free事件的整理事件
- Cache Buffer Chain Latch等待事件AI事件
- latch free事件的整理(轉)事件
- latch:library cache lock等待事件事件
- cache buffer lru chain latch等待事件AI事件
- [20170324]cpu 100%,latch free等待分析
- ORACLE等待事件latch: cache buffers chainsOracle事件AI
- 【效能調整】等待事件(九) latch原理事件
- 等待事件_cache_buffers_chains_latch事件AI
- 等待事件_cache_buffers_lru_chain_latch事件AI
- [20211229]再論19c latch free等待事件分析.txt事件
- [異常等待事件latch undo global data]分析事件
- 轉_診斷latch:shared pool等待事件事件
- buffer cache與相關的latch等待事件事件
- 【效能調整】等待事件(十) 10g中的latch等待事件
- 處理 latch_cache_buffers_chains等待事件一例AI事件
- oracle library cache相關的等待事件及latchOracle事件
- 長時間latch free等待——記一次系統異常的診斷過程
- 模擬產生CBC LATCH與buffer busy wait等待事件AI事件
- 12c設定RESULT_CACHE_MODE=MANUAL發生'Result Cache:RC Latch'型別的Latch Free等待型別
- oracle等待事件一Oracle事件
- Oracle 等待事件 一Oracle事件
- oracle一次卡頓案例(六)-latch freeOracle
- latch free(cache buffers chain)AI