ORACLE LOCK,LATCH,PIN

Davis_itpub發表於2018-06-27
Latch是Oracle提供的輕量級鎖,它用於快速,短時間的鎖定資源,防止多個併發程式同時修改訪問某個共享資源,它只工作在記憶體中,我們可以不大準確的說,記憶體中資源的鎖叫latch,資料庫物件(表,索引等)的鎖叫Lock。

比如資料快取中的某個塊要被讀取,我們會獲得這個塊的latch,這個過程叫做pin,另外一個程式恰好要修改這個塊,他也要pin這個塊,此時他必須等待,當前一個程式釋放latch後才能pin住,然後修改,如果多個程式同時請求的話,他們之間將出現競爭,沒有一個入隊機制,一旦前面程式釋放latch,後面的程式就蜂擁而上,沒有先來後到的概念,這個和Lock是有本質區別的,這一切都發生的非常快,因為Latch的特點是快而短暫,當然這個只是大致過程。

先來看下Latch和Lock的區別

1。 Latch是對記憶體資料結構提供互斥訪問的一種機制,而Lock是以不同的模式來套取共享資源物件,各個模式間存在著相容或排斥,從這點看出,Latch 的訪問,包括查詢也是互斥的,任何時候,只能有一個程式能pin住記憶體的某一塊,幸好這個過程是相當的短暫,否則系統效能將沒的保障,現在從9I開始,允許多個程式同時查詢相同的記憶體塊,但效能並沒有想象中的好。

2。 Latch只作用於記憶體中,他只能被當前例項訪問,而L ock作用於資料庫物件,在RAC體系中例項間允許Lock檢測與訪問

3。 Latch是瞬間的佔用,釋放,Lock的釋放需要等到事務正確的結束,他佔用的時間長短由事務大小決定

4。 Latch是非入隊的,而Lock是入隊的

5。 Latch不存在死鎖,而Lock中存在(死鎖在Oracle中是非常少見的)

看看下面這個例子,你會感覺到Latch的存在 


SQLCREATETABLEMYTESTASSELECTOBJECT_NAMEFROMUSER_OBJECTSWHEREROWNUM=4;
Tablecreated
SQLSETTIMINGON
SQL
DECLARElv_nameVARCHAR2(25):=‘‘;
  BEGIN
FORiIN1。。100000LOOP
   SELECTOBJECT_NAMEINTOlv_nameFROMMYTESTWHEREROWNUM=1;
ENDLOOP;
END;
/
PL/SQLproceduresuccessfullycompleted
Executedin3。359seconds
這個程式不斷的訪問表上的同一個資料塊,他先會物理讀取資料塊到資料緩衝區,然後在記憶體中不斷的獲取這個塊的latch,現在只有單個程式,執行的還好,10萬次用了3秒多,但當我拉出4個視窗同時併發的執行這個語句時,問題就出現了,多個程式PIN同一個資料塊,每個大概花了15秒,並且看到他們一個一個的結束,到最後只剩一個時一閃就過去了,因為沒人和他搶了,這個實驗展現了Latch競爭的現象,對於9I提出的查詢可以共享Latch在此我表示了質疑。

現在來看看程式獲取Latch的詳細過程,任何時候,只有一個程式可以訪問記憶體中的某一個塊(9I提出的Latch共享我不想考慮),如果程式因為別的程式正佔用塊而無法獲得Latch時,他會對CPU進行一次spin(旋轉),時間非常的短暫,spin過後繼續獲取,不成功仍然spin,直到 spin次數到達閥值限制(這個由隱含引數_spin_count指定),此時程式會停止spin,進行短期的休眠,休眠過後會繼續剛才的動作,直到獲取塊上的Latch為止。程式休眠的時間也是存在演算法的,他會隨著spin次數而遞增,以釐秒為單位,如1,1,2,2,4,4,8,8,。。。休眠的閥值限制由隱含引數_max_exponential_sleep控制,預設是2秒,如果當前程式已經佔用了別的Latch,則他的休眠時間不會太長(過長會引起別的程式的Latch等待),此時的休眠最大時間有隱含引數_max_sleep_holding_latch決定,默

認是4釐秒。這種時間限制的休眠又稱為短期等待,另外一種情況是長期等待鎖存器(Latch Wait Posting),此時等待程式請求Latch不成功,進入休眠,他會向鎖存器等待連結串列(Latch Wait List)壓入一條訊號,表示獲取Latch的請求,當佔用程式釋放Latch時會檢查Latch Wait List,向請求的程式傳遞一個訊號,啟用休眠的程式。Latch Wait List是在SGA區維護的一個程式列表,他也需要Latch來保證其正常執行,預設情況下share pool latch和library cache latch是採用這個機制,如果將隱含引數_latch_wait_posting設定為2,則所有Latch都採用這種等待方式,使用這種方式能夠比較精確的喚醒某個等待的程式,但維護Latch Wait List需要系統資源,並且對Latch Wait List上Latch的競爭也可能出現瓶頸。

如果一個程式請求,旋轉,休眠Latch用了很長時間,他會通知PMON程式,檢視Latch的佔用程式是否已經意外終止或死亡,如果是則PMON會清除釋放佔用的Latch資源。

現在大家可以明白,對Latch獲取的流程了,請求-SPIN-休眠-請求-SPIN-休眠。。。佔用,這裡有人會問為什麼要SPIN,為什麼不直接休眠等待?這裡要明白休眠意味著什麼,他意味著暫時的放棄CPU,進行上下文切換(context switch),這樣CPU要儲存當前程式執行時的一些狀態資訊,比如堆疊,訊號量等資料結構,然後引入後續程式的狀態資訊,處理完後再切換回原來的程式狀態,這個過程如果頻繁的發生在一個高事務,高併發程式的處理系統裡面,將是個很昂貴的資源消耗,所以他選擇了spin,讓程式繼續佔有CPU,執行一些空指令,之後繼續請求,繼續spin,直到達到_spin_count值,這時會放棄CPU,進行短暫的休眠,再繼續剛才的動作,Oracle軟體就是這麼設計的,世界大師們的傑作,自然有他的道理,我就不在這上面再費文字了。

系統發生關於Latch的等待是沒發避免的,因為這是Oracle的運作機制,當你看到很高的Latch get時並不意味著你的系統需要調整,有時候很高的get值背後只有很短的等待時間,我們調整的物件應該以消耗的時間來圈定,而不是看到一個很高的獲取次數值,當然,獲取值異常的高出別的等待時間幾十萬倍時我們還是要關心的,Oracle關於Latch的等待非常繁多,主要的包括share pool,library cache,cache buffer chains,buffer busy wait,每一個的調整幾乎都可以寫幾頁紙,以後慢慢完成吧。






-----------------------------------------------------------------------------------

Oracle使用兩種資料結構來進行shared pool的併發控制:lock 和 pin.
Lock比pin具有更高的級別.

Lock在handle上獲得,在pin一個物件之前,必須首先獲得該handle的鎖定.
鎖定主要有三種模式: Null,share,Exclusive.
在讀取訪問物件時,通常需要獲取Null(空)模式以及share(共享)模式的鎖定.
在修改物件時,需要獲得Exclusive(排他)鎖定.

在鎖定了Library Cache物件以後,一個程式在訪問之前必須pin該物件.
同樣pin有三種模式,Null,shared和exclusive.
只讀模式時獲得共享pin,修改模式獲得排他pin.

通常我們訪問、執行過程、Package時獲得的都是共享pin,如果排他pin被持有,那麼資料庫此時就要產生等待.


------------------------------------------------------------------------

library cache lock和library cache pin都是我們關心的.接下來我們就研究一下這幾個等待事件.

(一).LIBRARY CACHE PIN等待事件

Oracle文件上這樣介紹這個等待事件:
"library cache pin" 是用來管理library cache的併發訪問的,pin一個object會引起相應的heap被
載入記憶體中(如果此前沒有被載入),Pins可以在三個模式下獲得:NULL,SHARE,EXCLUSIVE,可以認為pin是一種特定
形式的鎖.
當Library Cache Pin等待事件出現時,通常說明該Pin被其他使用者已非相容模式持有.

"library cache pin"的等待時間為3秒鐘,其中有1秒鐘用於PMON後臺程式,即在取得pin之前最多等待3秒鐘,否則就超時.
"library cache pin"的引數如下,有用的主要是P1和P2:
               P1 - KGL Handle address.
               P2 - Pin address
               P3 - Encoded Mode & Namespace

"LIBRARY CACHE PIN"通常是發生在編譯或重新編譯PL/SQL,VIEW,TYPES等object時.編譯通常都是顯性的,
如安裝應用程式,升級,安裝補丁程式等,另外,"ALTER","GRANT","REVOKE"等操作也會使object變得無效,
可以透過object的"LAST_DDL"觀察這些變化.
當object變得無效時,Oracle 會在第一次訪問此object時試圖去重新編譯它,如果此時其他session已經把此object pin
到library cache中,就會出現問題,特別時當有大量的活動session並且存在較複雜的dependence時.在某種情況下,重新
編譯object可能會花幾個小時時間,從而阻塞其它試圖去訪問此object的程式.


----------------------------------------------------------------


Latch及latch衝突

引言
Oracle Rdbms應用了各種不同型別的鎖定機制,latch即是其中的一種,本文將集中介紹latch(閂)的概念,理解latch的實現方法並說明引起latch衝突的原因。

什麼是latch



Latch是用於保護SGA區中共享資料結構的一種序列化鎖定機制。Latch的實現是與作業系統相關的,尤其和一個程式是否需要等待一個latch、需要等待多長時間有關。

Latch是一種能夠極快地被獲取和釋放的鎖,它通常用於保護描述buffer cache中block的資料結構。與每個latch相聯絡的還有一個清除過程,當持有latch的程式成為死程式時,該清除過程就會被呼叫。Latch還具有相關級別,用於防止死鎖,一旦一個程式在某個級別上得到一個latch,它就不可能再獲得等同或低於該級別的latch。

Latch與Enqueue(佇列)

Enqueue是Oracle使用的另一種鎖定機制,它更加複雜,允許幾個併發程式不同程度地共享某些資源。任何可被併發使用的物件均可使用enqueue加以保護。一個典型的例子是表的鎖定,我們允許在一個表上有不同級別的共享。與latch不同之處在於,enqueue是使用作業系統特定的鎖定機制,一個enqueue允許使用者在鎖上存貯一個標記,來表明請求鎖的模式。作業系統lock manager跟蹤所有被鎖定的資源,如果某個程式不能獲取它所請求的那種鎖,作業系統就把請求程式置於一個等待佇列中,該佇列按FIFO原則排程,而在latches中是沒有象enqueue中排序的等待佇列,latch等待程式要麼使用定時器來喚醒和重試,要麼spin(只用於多處理器情況下)。

何時需要latch

當一個程式準備訪問SGA中的資料結構時,它就需要獲得一個latch。當程式獲得latch後,它將一直持有該latch直到它不再使用此資料結構,這時latch才會被釋放。可透過latch名稱來區分它所保護的不同資料結構。

Oracle使用元指令對latch進行操作, 當所需的latch已被其他程式持有時,執行指令程式將停止執行部分指令,直到該latch被釋放為止。從根本上講,latch防止併發訪問共享資料結構,由於設定和釋放latch的指令是不可分割的,作業系統就可以保證只有一個程式獲得latch,又由於這只是單條指令,所以執行速度很快。latch被持有的時間是很短,而且提供了當持有者不正常中斷時的清除機制,該清除工作是由Oracle後臺程式PMON來完成的。

什麼導致latch衝突

Latch保護SGA中的資料結構被多個使用者同時訪問,如果一個程式不能立即得到所需latch,它就必須等待,這就導致了CPU的額外負擔和系統的速度降低。額外的CPU使用是程式‘spining’導致的,‘spining’是指程式定時地重複嘗試獲取latch,在連續兩次之間,程式處於休眠狀態,在得到latch之前,spining過程將重複進行下去。

如何標識內部latch的衝突

Server manager monitor是一個相當有用的來監視latch等待、請求和衝突的工具。也可查詢相關的資料字典表:v$latch, v$latchholder, v$latchname。

v$latch表的每一行包括了對不同型別latch的統計,每一列反映了不同型別的latch請求的活動情況。不同型別的latch請求之間的區別在於,當latch不可立即獲得時,請求程式是否繼續進行。按此分類,latch請求的型別可分為兩類:willing-to-wait和immediate。

Willing-to-wait : 是指如果所請求的latch不能立即得到,請求程式將等待一很短的時間後再次發出請求。程式一直重複此過程直到得到latch。

Immediate:是指如果所請求的latch不能立即得到,請求程式就不再等待,而是繼續執行下去。

在v$latch中的以下欄位反映了Willing-to-wait請求:

GETS---成功地以Willing-to-wait請求型別請求一個latch的次數。

MISSES---初始以Willing-to-wait請求型別請求一個latch不成功的次數。

SLEEPS---初始以Willing-to-wait請求型別請求一個latch不成功後,程式等待獲取latch的次數。

在v$latch中的以下欄位反映了Immediate類請求:

IMMEDIATE_GETS---以Immediate請求型別成功地獲得一個latch的次數。

IMMEDIATE_MISSES---以Immediate請求型別請求一個latch不成功的次數。

我們可以透過對v$latch, v$latchholder, v$latchname的查詢獲得有關latch資訊,例如:

/* 已知一個latch地址,找到latch名字 */

col name for a40

select a.name from v$latchname a, v$latch b

where b.addr = '&addr'

and b.latch#=a.latch#;

/* 顯示系統範圍內的latch統計 */

column name format A32 truncate heading "LATCH NAME"

column pid heading "HOLDER PID"

select c.name,a.addr,a.gets,a.misses,a.sleeps,

a.immediate_gets,a.immediate_misses,b.pid

from v$latch a, v$latchholder b, v$latchname c

where a.addr = b.laddr(+)

and a.latch# = c.latch#

order by a.latch#;

/* 由latch名稱顯示對latch的統計 */

select c.name,a.addr,a.gets,a.misses,a.sleeps,

a.immediate_gets,a.immediate_misses,b.pid

from v$latch a, v$latchholder b, v$latchname c

where a.addr = b.laddr(+) and a.latch# = c.latch#



and c.name like '&latch_name%' order by a.latch#;

latch有40餘種,但作為DBA關心的主要應有以下幾種:

Cache buffers chains latch: 當使用者程式搜尋SGA尋找database cache buffers時需要使用此latch。

Cache buffers LRU chain latch: 當使用者程式要搜尋buffer cache中包括所有 dirty blocks的LRU (least recently used) 鏈時使用該種latch。

Redo log buffer latch: 這種latch控制redo log buffer中每條redo entries的空間分配。

Row cache objects latch: 當使用者程式訪問快取的資料字典數值時,將使用Row cache objects latch。

下面我們將著重介紹一下如何檢測和減少redo log buffer latch的衝突。對redo log buffer的訪問是由redo log buffer latch來控制的,這種latch有兩種型別, redo allocation latch和redo copy latch。

Redo allocation latch控制redo entries在redo log buffer中的空間分配。Oracle的一個使用者程式只有得到redo allocation latch後才能為redo entries在redo log buffer中分配空間,又由於一個instance只有一個redo allocation latch,所以一次只有一個使用者程式在buffer中分配空間。當使用者程式獲得latch後,首先為redo entry分配空間,然後程式繼續持有latch並複製entry到buffer中,這種複製稱為“在redo allocation latch上的複製”(copying on the redo allocation latch),複製完畢後,使用者程式釋放該latch。

一個“在redo allocation latch上的複製”的redo entry的最大值是由初始化引數LOG_SMALL_ENTRY_MAX_SIZE定義的,根據作業系統的不同而不同。

Redo Copy Latch只應用於多CPU的系統。在多CPU的instance中,如果一個redo entry太大,超過了LOG_SMALL_ENTRY_MAX_SIZE定義值,則不能進行“在redo allocation latch上的複製”, 此時使用者程式必須獲取redo copy latch。一個instance中可以有多個redo copy latch,其數目由初始引數LOG_SIMULTANEOUS_COPIES決定,預設值為CPU數目。

在單CPU情況下,不存在redo copy latch,所有的redo entry無論大小, 都進行“在redo allocation latch上的複製”。

對redo log buffer的過多訪問將導致redo log buffer latch的衝突,latch衝突將降低系統效能,我們可透過如下查詢來檢測這種latch衝突:

col name for a40

SELECT ln.name,gets,misses,immediate_gets,immediate_misses

FROM v$latch l,v$latchname ln

WHERE ln.name IN('redo allocation','redo copy') AND ln.latch#=l.latch#

/

若misses與gets的比例超過1%或immediate_misses與(immediate_gets+immediate_misses)比例超過1%時,應考慮採取措施減少latch的衝突。

大多數的redo log buffer latch衝突是在多個CPU情況下,兩個或多個Oracle程式試圖同時得到相同的latch發生的。由於一個instance只有一個redo allocation latch,為減少redo allocation latch的衝突,應減少單個程式持有latch的時間,這可以透過減小初始引數LOG_SMALL_ENTRY_MAX_SIZE以減小redo entry的數目和大小來實現。如果觀察到有redo copy latch衝突,可以透過增大LOG_SIMULTANEOUS_COPIES 初始引數來加大latch數目,其預設值為CPU數目,最大可增大到CPU數目的兩倍。




-----------------------------------------------------------------------------------

Oracle使用兩種資料結構來進行shared pool的併發控制:lock 和 pin.
Lock比pin具有更高的級別.

Lock在handle上獲得,在pin一個物件之前,必須首先獲得該handle的鎖定.
鎖定主要有三種模式: Null,share,Exclusive.
在讀取訪問物件時,通常需要獲取Null(空)模式以及share(共享)模式的鎖定.
在修改物件時,需要獲得Exclusive(排他)鎖定.

在鎖定了Library Cache物件以後,一個程式在訪問之前必須pin該物件.
同樣pin有三種模式,Null,shared和exclusive.
只讀模式時獲得共享pin,修改模式獲得排他pin.

通常我們訪問、執行過程、Package時獲得的都是共享pin,如果排他pin被持有,那麼資料庫此時就要產生等待.


------------------------------------------------------------------------

library cache lock和library cache pin都是我們關心的.接下來我們就研究一下這幾個等待事件.

(一).LIBRARY CACHE PIN等待事件

Oracle文件上這樣介紹這個等待事件:
"library cache pin" 是用來管理library cache的併發訪問的,pin一個object會引起相應的heap被
載入記憶體中(如果此前沒有被載入),Pins可以在三個模式下獲得:NULL,SHARE,EXCLUSIVE,可以認為pin是一種特定
形式的鎖.
當Library Cache Pin等待事件出現時,通常說明該Pin被其他使用者已非相容模式持有.

"library cache pin"的等待時間為3秒鐘,其中有1秒鐘用於PMON後臺程式,即在取得pin之前最多等待3秒鐘,否則就超時.
"library cache pin"的引數如下,有用的主要是P1和P2:
               P1 - KGL Handle address.
               P2 - Pin address
               P3 - Encoded Mode & Namespace

"LIBRARY CACHE PIN"通常是發生在編譯或重新編譯PL/SQL,VIEW,TYPES等object時.編譯通常都是顯性的,
如安裝應用程式,升級,安裝補丁程式等,另外,"ALTER","GRANT","REVOKE"等操作也會使object變得無效,
可以透過object的"LAST_DDL"觀察這些變化.
當object變得無效時,Oracle 會在第一次訪問此object時試圖去重新編譯它,如果此時其他session已經把此object pin
到library cache中,就會出現問題,特別時當有大量的活動session並且存在較複雜的dependence時.在某種情況下,重新
編譯object可能會花幾個小時時間,從而阻塞其它試圖去訪問此object的程式.


-------------------------------------------------------------------------


Latch及latch衝突

引言
Oracle Rdbms應用了各種不同型別的鎖定機制,latch即是其中的一種,本文將集中介紹latch(閂)的概念,理解latch的實現方法並說明引起latch衝突的原因。

什麼是latch



Latch是用於保護SGA區中共享資料結構的一種序列化鎖定機制。Latch的實現是與作業系統相關的,尤其和一個程式是否需要等待一個latch、需要等待多長時間有關。

Latch是一種能夠極快地被獲取和釋放的鎖,它通常用於保護描述buffer cache中block的資料結構。與每個latch相聯絡的還有一個清除過程,當持有latch的程式成為死程式時,該清除過程就會被呼叫。Latch還具有相關級別,用於防止死鎖,一旦一個程式在某個級別上得到一個latch,它就不可能再獲得等同或低於該級別的latch。

Latch與Enqueue(佇列)

Enqueue是Oracle使用的另一種鎖定機制,它更加複雜,允許幾個併發程式不同程度地共享某些資源。任何可被併發使用的物件均可使用enqueue加以保護。一個典型的例子是表的鎖定,我們允許在一個表上有不同級別的共享。與latch不同之處在於,enqueue是使用作業系統特定的鎖定機制,一個enqueue允許使用者在鎖上存貯一個標記,來表明請求鎖的模式。作業系統lock manager跟蹤所有被鎖定的資源,如果某個程式不能獲取它所請求的那種鎖,作業系統就把請求程式置於一個等待佇列中,該佇列按FIFO原則排程,而在latches中是沒有象enqueue中排序的等待佇列,latch等待程式要麼使用定時器來喚醒和重試,要麼spin(只用於多處理器情況下)。

何時需要latch

當一個程式準備訪問SGA中的資料結構時,它就需要獲得一個latch。當程式獲得latch後,它將一直持有該latch直到它不再使用此資料結構,這時latch才會被釋放。可透過latch名稱來區分它所保護的不同資料結構。

Oracle使用元指令對latch進行操作, 當所需的latch已被其他程式持有時,執行指令程式將停止執行部分指令,直到該latch被釋放為止。從根本上講,latch防止併發訪問共享資料結構,由於設定和釋放latch的指令是不可分割的,作業系統就可以保證只有一個程式獲得latch,又由於這只是單條指令,所以執行速度很快。latch被持有的時間是很短,而且提供了當持有者不正常中斷時的清除機制,該清除工作是由Oracle後臺程式PMON來完成的。

什麼導致latch衝突

Latch保護SGA中的資料結構被多個使用者同時訪問,如果一個程式不能立即得到所需latch,它就必須等待,這就導致了CPU的額外負擔和系統的速度降低。額外的CPU使用是程式‘spining’導致的,‘spining’是指程式定時地重複嘗試獲取latch,在連續兩次之間,程式處於休眠狀態,在得到latch之前,spining過程將重複進行下去。

如何標識內部latch的衝突

Server manager monitor是一個相當有用的來監視latch等待、請求和衝突的工具。也可查詢相關的資料字典表:v$latch, v$latchholder, v$latchname。

v$latch表的每一行包括了對不同型別latch的統計,每一列反映了不同型別的latch請求的活動情況。不同型別的latch請求之間的區別在於,當latch不可立即獲得時,請求程式是否繼續進行。按此分類,latch請求的型別可分為兩類:willing-to-wait和immediate。

Willing-to-wait : 是指如果所請求的latch不能立即得到,請求程式將等待一很短的時間後再次發出請求。程式一直重複此過程直到得到latch。

Immediate:是指如果所請求的latch不能立即得到,請求程式就不再等待,而是繼續執行下去。

在v$latch中的以下欄位反映了Willing-to-wait請求:

GETS---成功地以Willing-to-wait請求型別請求一個latch的次數。

MISSES---初始以Willing-to-wait請求型別請求一個latch不成功的次數。

SLEEPS---初始以Willing-to-wait請求型別請求一個latch不成功後,程式等待獲取latch的次數。

在v$latch中的以下欄位反映了Immediate類請求:

IMMEDIATE_GETS---以Immediate請求型別成功地獲得一個latch的次數。

IMMEDIATE_MISSES---以Immediate請求型別請求一個latch不成功的次數。

我們可以透過對v$latch, v$latchholder, v$latchname的查詢獲得有關latch資訊,例如:

/* 已知一個latch地址,找到latch名字 */

col name for a40

select a.name from v$latchname a, v$latch b

where b.addr = '&addr'

and b.latch#=a.latch#;

/* 顯示系統範圍內的latch統計 */

column name format A32 truncate heading "LATCH NAME"

column pid heading "HOLDER PID"

select c.name,a.addr,a.gets,a.misses,a.sleeps,

a.immediate_gets,a.immediate_misses,b.pid

from v$latch a, v$latchholder b, v$latchname c

where a.addr = b.laddr(+)

and a.latch# = c.latch#

order by a.latch#;

/* 由latch名稱顯示對latch的統計 */

select c.name,a.addr,a.gets,a.misses,a.sleeps,

a.immediate_gets,a.immediate_misses,b.pid

from v$latch a, v$latchholder b, v$latchname c

where a.addr = b.laddr(+) and a.latch# = c.latch#



and c.name like '&latch_name%' order by a.latch#;

latch有40餘種,但作為DBA關心的主要應有以下幾種:

Cache buffers chains latch: 當使用者程式搜尋SGA尋找database cache buffers時需要使用此latch。

Cache buffers LRU chain latch: 當使用者程式要搜尋buffer cache中包括所有 dirty blocks的LRU (least recently used) 鏈時使用該種latch。

Redo log buffer latch: 這種latch控制redo log buffer中每條redo entries的空間分配。

Row cache objects latch: 當使用者程式訪問快取的資料字典數值時,將使用Row cache objects latch。

下面我們將著重介紹一下如何檢測和減少redo log buffer latch的衝突。對redo log buffer的訪問是由redo log buffer latch來控制的,這種latch有兩種型別, redo allocation latch和redo copy latch。

Redo allocation latch控制redo entries在redo log buffer中的空間分配。Oracle的一個使用者程式只有得到redo allocation latch後才能為redo entries在redo log buffer中分配空間,又由於一個instance只有一個redo allocation latch,所以一次只有一個使用者程式在buffer中分配空間。當使用者程式獲得latch後,首先為redo entry分配空間,然後程式繼續持有latch並複製entry到buffer中,這種複製稱為“在redo allocation latch上的複製”(copying on the redo allocation latch),複製完畢後,使用者程式釋放該latch。

一個“在redo allocation latch上的複製”的redo entry的最大值是由初始化引數LOG_SMALL_ENTRY_MAX_SIZE定義的,根據作業系統的不同而不同。

Redo Copy Latch只應用於多CPU的系統。在多CPU的instance中,如果一個redo entry太大,超過了LOG_SMALL_ENTRY_MAX_SIZE定義值,則不能進行“在redo allocation latch上的複製”, 此時使用者程式必須獲取redo copy latch。一個instance中可以有多個redo copy latch,其數目由初始引數LOG_SIMULTANEOUS_COPIES決定,預設值為CPU數目。

在單CPU情況下,不存在redo copy latch,所有的redo entry無論大小, 都進行“在redo allocation latch上的複製”。

對redo log buffer的過多訪問將導致redo log buffer latch的衝突,latch衝突將降低系統效能,我們可透過如下查詢來檢測這種latch衝突:

col name for a40

SELECT ln.name,gets,misses,immediate_gets,immediate_misses

FROM v$latch l,v$latchname ln

WHERE ln.name IN('redo allocation','redo copy') AND ln.latch#=l.latch#

/

若misses與gets的比例超過1%或immediate_misses與(immediate_gets+immediate_misses)比例超過1%時,應考慮採取措施減少latch的衝突。

大多數的redo log buffer latch衝突是在多個CPU情況下,兩個或多個Oracle程式試圖同時得到相同的latch發生的。由於一個instance只有一個redo allocation latch,為減少redo allocation latch的衝突,應減少單個程式持有latch的時間,這可以透過減小初始引數LOG_SMALL_ENTRY_MAX_SIZE以減小redo entry的數目和大小來實現。如果觀察到有redo copy latch衝突,可以透過增大LOG_SIMULTANEOUS_COPIES 初始引數來加大latch數目,其預設值為CPU數目,最大可增大到CPU數目的兩倍。

轉自:http://space.itpub.net/35489/viewspace-664252

-----------------------------------------------------------------------------------



Oracle使用兩種資料結構來進行shared pool的併發控制:lock 和 pin.
Lock比pin具有更高的級別.

Lock在handle上獲得,在pin一個物件之前,必須首先獲得該handle的鎖定.
鎖定主要有三種模式: Null,share,Exclusive.
在讀取訪問物件時,通常需要獲取Null(空)模式以及share(共享)模式的鎖定.
在修改物件時,需要獲得Exclusive(排他)鎖定.

在鎖定了Library Cache物件以後,一個程式在訪問之前必須pin該物件.
同樣pin有三種模式,Null,shared和exclusive.
只讀模式時獲得共享pin,修改模式獲得排他pin.

通常我們訪問、執行過程、Package時獲得的都是共享pin,如果排他pin被持有,那麼資料庫此時就要產生等待.




------------------------------------------------------------------------



library cache lock和library cache pin都是我們關心的.接下來我們就研究一下這幾個等待事件.

(一).LIBRARY CACHE PIN等待事件

Oracle文件上這樣介紹這個等待事件:
"library cache pin" 是用來管理library cache的併發訪問的,pin一個object會引起相應的heap被
載入記憶體中(如果此前沒有被載入),Pins可以在三個模式下獲得:NULL,SHARE,EXCLUSIVE,可以認為pin是一種特定
形式的鎖.
當Library Cache Pin等待事件出現時,通常說明該Pin被其他使用者已非相容模式持有.

"library cache pin"的等待時間為3秒鐘,其中有1秒鐘用於PMON後臺程式,即在取得pin之前最多等待3秒鐘,否則就超時.
"library cache pin"的引數如下,有用的主要是P1和P2:
               P1 - KGL Handle address.
               P2 - Pin address
               P3 - Encoded Mode & Namespace

"LIBRARY CACHE PIN"通常是發生在編譯或重新編譯PL/SQL,VIEW,TYPES等object時.編譯通常都是顯性的,
如安裝應用程式,升級,安裝補丁程式等,另外,"ALTER","GRANT","REVOKE"等操作也會使object變得無效,
可以透過object的"LAST_DDL"觀察這些變化.
當object變得無效時,Oracle 會在第一次訪問此object時試圖去重新編譯它,如果此時其他session已經把此object pin
到library cache中,就會出現問題,特別時當有大量的活動session並且存在較複雜的dependence時.在某種情況下,重新
編譯object可能會花幾個小時時間,從而阻塞其它試圖去訪問此object的程式.


------------------------------------------------------------------------------------------------------------






Latch及latch衝突

引言
Oracle Rdbms應用了各種不同型別的鎖定機制,latch即是其中的一種,本文將集中介紹latch(閂)的概念,理解latch的實現方法並說明引起latch衝突的原因。

什麼是latch






Latch是用於保護SGA區中共享資料結構的一種序列化鎖定機制。Latch的實現是與作業系統相關的,尤其和一個程式是否需要等待一個latch、需要等待多長時間有關。

Latch是一種能夠極快地被獲取和釋放的鎖,它通常用於保護描述buffer cache中block的資料結構。與每個latch相聯絡的還有一個清除過程,當持有latch的程式成為死程式時,該清除過程就會被呼叫。Latch還具有相關級別,用於防止死鎖,一旦一個程式在某個級別上得到一個latch,它就不可能再獲得等同或低於該級別的latch。

Latch與Enqueue(佇列)

Enqueue是Oracle使用的另一種鎖定機制,它更加複雜,允許幾個併發程式不同程度地共享某些資源。任何可被併發使用的物件均可使用enqueue加以保護。一個典型的例子是表的鎖定,我們允許在一個表上有不同級別的共享。與latch不同之處在於,enqueue是使用作業系統特定的鎖定機制,一個enqueue允許使用者在鎖上存貯一個標記,來表明請求鎖的模式。作業系統lock manager跟蹤所有被鎖定的資源,如果某個程式不能獲取它所請求的那種鎖,作業系統就把請求程式置於一個等待佇列中,該佇列按FIFO原則排程,而在latches中是沒有象enqueue中排序的等待佇列,latch等待程式要麼使用定時器來喚醒和重試,要麼spin(只用於多處理器情況下)。

何時需要latch

當一個程式準備訪問SGA中的資料結構時,它就需要獲得一個latch。當程式獲得latch後,它將一直持有該latch直到它不再使用此資料結構,這時latch才會被釋放。可透過latch名稱來區分它所保護的不同資料結構。

Oracle使用元指令對latch進行操作, 當所需的latch已被其他程式持有時,執行指令程式將停止執行部分指令,直到該latch被釋放為止。從根本上講,latch防止併發訪問共享資料結構,由於設定和釋放latch的指令是不可分割的,作業系統就可以保證只有一個程式獲得latch,又由於這只是單條指令,所以執行速度很快。latch被持有的時間是很短,而且提供了當持有者不正常中斷時的清除機制,該清除工作是由Oracle後臺程式PMON來完成的。

什麼導致latch衝突

Latch保護SGA中的資料結構被多個使用者同時訪問,如果一個程式不能立即得到所需latch,它就必須等待,這就導致了CPU的額外負擔和系統的速度降低。額外的CPU使用是程式‘spining’導致的,‘spining’是指程式定時地重複嘗試獲取latch,在連續兩次之間,程式處於休眠狀態,在得到latch之前,spining過程將重複進行下去。

如何標識內部latch的衝突

Server manager monitor是一個相當有用的來監視latch等待、請求和衝突的工具。也可查詢相關的資料字典表:v$latch, v$latchholder, v$latchname。

v$latch表的每一行包括了對不同型別latch的統計,每一列反映了不同型別的latch請求的活動情況。不同型別的latch請求之間的區別在於,當latch不可立即獲得時,請求程式是否繼續進行。按此分類,latch請求的型別可分為兩類:willing-to-wait和immediate。

Willing-to-wait : 是指如果所請求的latch不能立即得到,請求程式將等待一很短的時間後再次發出請求。程式一直重複此過程直到得到latch。

Immediate:是指如果所請求的latch不能立即得到,請求程式就不再等待,而是繼續執行下去。

在v$latch中的以下欄位反映了Willing-to-wait請求:

GETS---成功地以Willing-to-wait請求型別請求一個latch的次數。

MISSES---初始以Willing-to-wait請求型別請求一個latch不成功的次數。

SLEEPS---初始以Willing-to-wait請求型別請求一個latch不成功後,程式等待獲取latch的次數。

在v$latch中的以下欄位反映了Immediate類請求:

IMMEDIATE_GETS---以Immediate請求型別成功地獲得一個latch的次數。

IMMEDIATE_MISSES---以Immediate請求型別請求一個latch不成功的次數。

我們可以透過對v$latch, v$latchholder, v$latchname的查詢獲得有關latch資訊,例如:

/* 已知一個latch地址,找到latch名字 */

col name for a40

select a.name from v$latchname a, v$latch b

where b.addr = '&addr'

and b.latch#=a.latch#;

/* 顯示系統範圍內的latch統計 */

column name format A32 truncate heading "LATCH NAME"

column pid heading "HOLDER PID"

select c.name,a.addr,a.gets,a.misses,a.sleeps,

a.immediate_gets,a.immediate_misses,b.pid

from v$latch a, v$latchholder b, v$latchname c

where a.addr = b.laddr(+)

and a.latch# = c.latch#

order by a.latch#;

/* 由latch名稱顯示對latch的統計 */

select c.name,a.addr,a.gets,a.misses,a.sleeps,

a.immediate_gets,a.immediate_misses,b.pid

from v$latch a, v$latchholder b, v$latchname c

where a.addr = b.laddr(+) and a.latch# = c.latch#



and c.name like '&latch_name%' order by a.latch#;

latch有40餘種,但作為DBA關心的主要應有以下幾種:

Cache buffers chains latch: 當使用者程式搜尋SGA尋找database cache buffers時需要使用此latch。

Cache buffers LRU chain latch: 當使用者程式要搜尋buffer cache中包括所有 dirty blocks的LRU (least recently used) 鏈時使用該種latch。

Redo log buffer latch: 這種latch控制redo log buffer中每條redo entries的空間分配。

Row cache objects latch: 當使用者程式訪問快取的資料字典數值時,將使用Row cache objects latch。

下面我們將著重介紹一下如何檢測和減少redo log buffer latch的衝突。對redo log buffer的訪問是由redo log buffer latch來控制的,這種latch有兩種型別, redo allocation latch和redo copy latch。

Redo allocation latch控制redo entries在redo log buffer中的空間分配。Oracle的一個使用者程式只有得到redo allocation latch後才能為redo entries在redo log buffer中分配空間,又由於一個instance只有一個redo allocation latch,所以一次只有一個使用者程式在buffer中分配空間。當使用者程式獲得latch後,首先為redo entry分配空間,然後程式繼續持有latch並複製entry到buffer中,這種複製稱為“在redo allocation latch上的複製”(copying on the redo allocation latch),複製完畢後,使用者程式釋放該latch。

一個“在redo allocation latch上的複製”的redo entry的最大值是由初始化引數LOG_SMALL_ENTRY_MAX_SIZE定義的,根據作業系統的不同而不同。

Redo Copy Latch只應用於多CPU的系統。在多CPU的instance中,如果一個redo entry太大,超過了LOG_SMALL_ENTRY_MAX_SIZE定義值,則不能進行“在redo allocation latch上的複製”, 此時使用者程式必須獲取redo copy latch。一個instance中可以有多個redo copy latch,其數目由初始引數LOG_SIMULTANEOUS_COPIES決定,預設值為CPU數目。

在單CPU情況下,不存在redo copy latch,所有的redo entry無論大小, 都進行“在redo allocation latch上的複製”。

對redo log buffer的過多訪問將導致redo log buffer latch的衝突,latch衝突將降低系統效能,我們可透過如下查詢來檢測這種latch衝突:

col name for a40

SELECT ln.name,gets,misses,immediate_gets,immediate_misses

FROM v$latch l,v$latchname ln

WHERE ln.name IN('redo allocation','redo copy') AND ln.latch#=l.latch#

/

若misses與gets的比例超過1%或immediate_misses與(immediate_gets+immediate_misses)比例超過1%時,應考慮採取措施減少latch的衝突。

大多數的redo log buffer latch衝突是在多個CPU情況下,兩個或多個Oracle程式試圖同時得到相同的latch發生的。由於一個instance只有一個redo allocation latch,為減少redo allocation latch的衝突,應減少單個程式持有latch的時間,這可以透過減小初始引數LOG_SMALL_ENTRY_MAX_SIZE以減小redo entry的數目和大小來實現。如果觀察到有redo copy latch衝突,可以透過增大LOG_SIMULTANEOUS_COPIES 初始引數來加大latch數目,其預設值為CPU數目,最大可增大到CPU數目的兩倍。

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

相關文章