教你如何成為Oracle 10g OCP - 第十章 閂鎖、鎖定和併發性

tolywang發表於2010-08-09

 

序列化 - 資料庫系統本身是一個多使用者併發處理系統,在同一個時間點上,
可能會有多個使用者同時運算元據庫, 多個使用者同時在相同的物理位置上寫數
據時,不能發生互相覆蓋的情況,這叫做序列化,序列化會降低系統的併發性,
但這對於保護資料結構不被破壞來說則是必需的。


在Oracle資料庫中,透過閂鎖(latch)和鎖定(lock)來解決這兩個問題。


Latch與Lock --

閂鎖和鎖定既有相同點又有不同點。相同點在於它們都是用於實現序列化的
資源。而不同點則在於閂鎖(Latch)是一個低階別、輕量級的鎖,獲得和釋
放的速度很快,以類似於訊號燈的方式實現。而鎖定(Lock)則可能持續的時
間很長,透過使用佇列,按照先進先出的方式實現。也可以簡單地理解為閂鎖
是微觀領域的,而鎖定則是宏觀領域的。


10.1  閂鎖(latch)概述


什麼是Latch ---

Oracle資料庫使用閂鎖(latch)來管理SGA記憶體的分配和釋放.


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

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

 

Latch的種類 ---

sga有多個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。

 


Latch如何工作 ---

比如A程式需要更新58號資料塊,對應伺服器程式將58號資料塊讀入data buffer
中,要向data buffer中的58號資料塊(在data buffer中記憶體單位是資料塊)寫數
據時,必須先獲得latch,然後開始寫動作,如果在A正在寫入的過程中,B程式
也要寫58號資料塊,這時B嘗試獲得在58號資料塊上的latch,發現該latch正被其
它使用者A持有,B進入等待狀態,直到A寫完資料塊並釋放latch後,B才能獲得latch,
獲得latch後才能向58號資料塊寫入資料。否則如果沒有latch保護,那麼A,B
同時寫同一個實體地址(記憶體空間)會導致資料覆蓋而出現資料混亂。


事實上,latch不僅僅用於寫資料塊,比如對於shared pool來說,其記憶體單位就不
是資料塊了(而是chunk)。latch也不僅僅用於寫操作,只要涉及記憶體地址的讀和寫,
都需要透過獲得latch來實現序列化,一次只能有一個伺服器程式在讀或者寫記憶體
地址。

Oracle在例項管理中,不管是buffer cache、shared pool還是log buffer,都引
入了各種各樣的latch。

-- 備註:  log buffer的最小記憶體單位是OS block.


實現latch時,實際是由作業系統的旗語(semaphore:也叫訊號量)來完成的。
為了便於理解,可以把它們想象為,透過某個變數值的變化而實現的。變數值
為0則說明latch當前沒有被其他程式獲取,否則如果為非0值,則說明它已經被
其他程式所獲取了。Oracle在設計latch的時候將其定義為輕量級鎖,因此它的
操作非常快,以微秒(microsecond,也就是百萬分之一秒)來計算。


-------------------------------------------------------
網路文摘:

任何時候,只有一個程式可以訪問記憶體中的某一個塊,會話A在調整一個LRU連結串列
的時候,其它的會話就不能讀取和調整這個連結串列了,latch所做的就是保護這一點。

備註: 記憶體中的塊針對buffer cache,shared pool及log buffer而言大小單位
分別是oracle block, chunk及os block ???

http://blog.csdn.net/Jermaine/archive/2010/08/01/5780661.aspx

http://blog.csdn.net/Jermaine/archive/2010/08/01/5780661.aspx

latch是一種低階的序列化裝置,它是為了保護SGA共享記憶體結構免受併發訪問帶
來的潛在性破壞而引入的一種串性化手段,它只與SGA共享記憶體結構有關,與資料
庫物件無關。絕大多數latch是獨佔性訪問,只有少數共享latch允許併發讀。


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

 

 


-- Latch的種類

A. 願意等待(Willing-To-Wait)

SPIN -  SPIN 就是一個程式獨佔CPU time,直到執行的結束。這個期間其他
程式不能獲得這個CPU的執行時間。Oracle 允許一個程式迴圈spin 一顆CPU
(當然需要OS支援)。  單CPU 沒有SPIN的概念了。

 

大部分的latch都屬於這種型別(Willing-To-Wait)。這種型別的latch都是
透過Test-And-Set的方式來實現的。也就是說,如果當前程式不能獲得latch
的時候,會繞著CPU旋轉但不放棄CPU(佔用)。這也就是所謂的SPIN CPU.


如果程式不能馬上獲得latch,會繞著CPU轉一會(佔著CPU),然後再次嘗試
獲得latch,如果仍然不能獲得,則再次旋轉CPU。當反覆旋轉CPU並嘗試獲
得latch的的次數超過某個上限(該上限由隱藏引數控制)時,這時程式
會釋放CPU,並進入睡眠(Sleep)狀態。程式一旦進入睡眠狀態,則會丟擲
一個對應的等待事件,並記錄在檢視v$session_wait裡,說明當前該程式
正在等待的latch的型別等資訊。 初始狀態下,一個程式會睡眠0.01秒。
然後醒過來,並再次嘗試獲得latch。如果旋轉CPU的次數達到上限以後,
仍然不能獲得latch,則再次進入睡眠,這時會睡眠兩倍的時間,依此類推,
直到達到睡眠的最大值:0.2秒。這是在資料庫伺服器具有多個CPU時的情形,
如果只有一個CPU,就不存在旋轉CPU(SPIN CPU)的情況,一旦獲得不了
latch,就進入睡眠。


總的來說,當程式嘗試獲取Willing-To-Wait型別的latch時,如果失敗,
則程式會一直嘗試對latch的獲取,不斷迴圈,直到獲得latch為止,或
者是達到所指定的上限值為止。當達到上限值時,程式進入睡眠。


B.  不等待(No-Wait)

這種型別的latch比較少,對於這種型別的latch來說,都會有很多個
可用的latch。當一個程式請求其中的一個latch時,會以no-wait模式
開始請求。如果所請求的latch不可用,則程式不會等待,而是立刻請
求另外一個latch。只有當所有的latch都不能獲得時,才會進入等待。

備註:latch是用於保護SGA區中共享資料結構的一種序列化鎖定機制。
它不僅僅用於buffer cache, 還用於shared pool以及log buffer等。

 


-- Latch資源爭用

如果latch資源被爭用,通常都會表現為CPU資源使用過高。


而反過來說,如果我們發現CPU資源很緊張,利用率總是在90%以上,
甚至總是在100%,其主要原因有以下幾點。

A. SQL語句沒有使用繫結變數。如果沒有使用繫結變數,要非常頻繁
地讀寫shared pool裡的記憶體塊,從而導致與解析SQL相關的latch爭用。

B. 執行SQL語句時,掃描的資料塊過多,或者說SQL語句寫的比較低效,
導致要掃描很多的資料塊才能返回所要的記錄。因為在查詢、掃描數
據塊的過程中,程式也要獲得latch,直到找到資料塊為止。

 

為何一旦latch資源發生爭用,就會導致CPU繁忙呢?可以想象一下,
假設某個程式(A)執行一條SQL語句需要訪問10000個資料塊,那麼
該程式在掃描資料塊的過程中,一直持有latch。而另一個程式B也要
執行SQL,但是由於A持有了latch,導致B無法獲得,於是旋轉一會CPU,
再去獲得latch,直到進入睡眠才釋放CPU。接下來C程式也要執行SQL,
同樣的,由於A持有了latch,導致C無法獲得,於是也旋轉一會CPU,
再去獲得latch,直到進入睡眠才釋放CPU。如果類似B和C的程式很多
的話,那我們會發現,CPU總是在被旋轉,也就是在做空的迴圈,而
無法做其他的事情。因此,體現出CPU的使用率過高。

 

要解決latch的爭用,關鍵在於共享SQL語句(比如使用繫結變數、
規範SQL的書寫等)以及最佳化SQL語句,使其搜尋以及掃描的資料塊的
個數下降到最低。

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

相關文章