一、什麼是Latch
1.1、 Latch是一種低級排隊(串行)機制,用於保護SGA中共享內存結構。1.2、 Latch是一種快速的被獲取和釋放的內存鎖,用於防止共享內存結構被多個用戶同時訪問。
1.3、 Latch請求的類型:willing-to-wait和immediate。 1.3.1 對於willing-to-wait類型的latch:
如果一個進程在第一次嘗試中沒有獲得latch,那麼它會等待並且再嘗試一次,如果經過_spin_count次爭奪不能獲得latch, 然後該進程轉入睡眠狀態,睡眠醒來後,按順序重複以前的步驟。睡眠的時間會越來越長。 1.3.2 對於immediate類型的latch:
如果該閂不能立即得到的話,那麼該進程就不會爲獲得該latch而等待。它將繼續執行另一個操作。
1.3.3 可以通過v$latch視圖查看latch的具體信息,在v$latch中:
(以下字段反映了Willing-to-wait類型請求)
GETS:成功地以Willing-to-wait請求類型請求一個latch的次數。
MISSES:初始以Willing-to-wait請求類型請求一個latch不成功的次數。
SLEEPS:初始以Willing-to-wait請求類型請求一個latch不成功後,進程等待獲取latch的次數。
(以下字段反映了Immediate類型請求)
IMMEDIATE_GETS:以Immediate請求類型成功地獲得一個latch的次數。 IMMEDIATE_MISSES:以Immediate請求類型請求一個latch不成功的次數。
1.4、 與隊列鎖(enqueue)不同的是:對於Latch的請求,不用排隊等待資源,由於Latch的分配相當隨機,所以當Latch釋放後,不管哪個會話請求都可能得到它,當不能獲得Latch的會話,就會在後續不斷的重試(spin->sleep->spin…->get latch)。 1.4.1 爲什麼自旋(spin)?
在一臺多CPU 的機器上,如果Latch不能立即獲得,那麼會話就會自旋,即在循環中反覆地嘗試來或得Latch。如果不這樣的話,那麼就會導致上下文切換(context switching),這樣對資源開銷更大
1.4.2 得到Latch的僞代碼如下:
Attemp to get Latch
If Latch gotten Then Return SUCCESS
Else Misses on that Latch = Misses + 1 Loop For I in 1 .. 2000(_spin_count) Loop Attempt to get Latch If Latch gotten Then
Return SUCCESS
End if End loop
Go to sleep for short period
Sleep on Latch = Sleeps + 1
End loop
End if
圖示如下:
所以,可以知道,當嘗試獲得Latch的時候,可能會消耗大量的CPU時間。系統看上去很忙,但並沒有做多少實際工作。
1.5、相關視圖 1.5.1 v$latch :
V$LATCH shows aggregate latch statistics for both parent and child latches, grouped by latch name.
1.5.2 v$latch_children:
V$LATCH_CHILDREN contains statistics about child latches. 1.5.3 v$latch_misses :
This view contains statistics about missed attempts to acquire a latch.
1.5.4 v$latchname : This view contains information about decoded latch names for the latches shown in V$LATCH
二、與BUFFER CACHE相關的Latch
2.1、和BUFFER CACHE相關的主要Latch有:
Latch:cache buffers lru chain Latch: cache buffers chains
既然Latch是用來保護共享內存塊不被並行破壞,那就瞭解BUFFER CACHE的相關原理,進而得知什麼時候需要用到這個Latch,才能夠有相應的解決方案。
2.2、BUFFER CACHE是用來緩存數據塊的地方,那麼數據的查詢和修改都要通過它來完成。接下來就看看訪問數據的流程是怎樣的: 2.2.1
當一個進程要訪問數據時,首先要查找BUFFER CACHE看看數據是否已經存在?
(Y) 如果數據在BUFFER CACHE中存在,則根據數據的狀態來判斷是否可以直接訪問還是需要構造一致性讀取?
(N) 如果數據在BUFFER CACHE中不存在,則需要從數據文件中讀取數據塊到BUFFER CACHE中去。這個時候,需要查找在BUFFER CACHE中尋找足夠的內存空間來讀取相關的數據。
2.2.2
現在BUFFER CACHE那麼大,一個BUFFER一個BUFFER的掃描過去是相當的消耗資源以及查詢的時間,那我們怎樣才能快速地查到數據了? 可以看看下面關於BUFFER CACHE的示圖:
這邊我們先看下面幾點:
1) 圖中右邊的有一塊Buffers Memory,其中每一塊小格就是一個Buffer(用來存放從數據文
件中讀取的數據塊Block)。
2) 圖中左邊的有許多Buffer Header用虛線指向Buffers Memory中的相應的Buffer。
3) 圖中左邊的有許多實線箭頭,這些箭頭(其實就是數據結構的鏈表結構中的指針)將不同的Buffer Header連接成一條Hash Chain,這邊也就是Cache Buffers Chain(雙向鏈表)。
4) 另外,還有一個Hash Bucket,其實這只是一個邏輯上的概念,即每一個Hash Bucket都
會有一條Hash Chain來將Buffer Header(按照HASH算法分類後)連接起來,並由一個Cache Buffers Chains Latch來進行管理其併發操作。
每當將一個Block讀入到Buffer Cache的時候,首先會構造一個與之對應的Buffer Header,然後根據HASH算法( Hash Bucket = MOD(Data Block Address, _DB_BLOCK_HASH_BUCKETS) ),將Buffer Header放到對應的Hash Bucket的Cache Buffers Chain中去,並在Buffer Header中
存放如下信息:
1.存放該Block在Buffer Cache中實際存儲地址
2.存放該Block的類型(data,segment header,undo header,undo Block等類型)
3.由於此Buffer Header 所在的Hash Chain,是通過在Buffer Header保存指向前一個Buffer Header的指針和指向後一個Buffer Header的指針方式實現,所以還存指針
4.存儲lru,lruw,ckptq,fileq等隊列,一樣是通過記錄前後Buffer Header指針方式實現
5.當前該Buffer Header所對應的數據塊的狀態以及標記
6.該Buffer Header被訪問的次數(touch次數)
7.正在等待該Buffer Header的進程列表(waiter list)及正在使用此Buffer Header的(user list)
未完待續。。。。
來自 http://wenku.baidu.com/view/41e024bd1a37f111f1855b95.html