Mutex的類型Mutex Type
Mutex的類型其實就是 mutex對應的客戶的名字, 在版本10.2中基本只有KKS使用Mutex,所以僅有3種:
Cursor Stat (kgx_kks1)
Cursor Parent (kgx_kks2)
Cursor Pin (kgx_kks3)
在版本11g中擴展了對Mutex的使用,在Library Cache的HASH BUCKET中嵌入了mutex以保護hash bucket,所以多了一種mutex type : Library Cache
哪些代碼函數會申請Mutex?
Oracle中哪些代碼函數會申請Mutex? 例如KKSFBC等,其實很像 V$LATCH的location列
10.2中最常見的下面的幾個函數
kkspsc0 -負責解析游標 - 檢測我們正在解析的游標是否有對象的parent cursor heap 0存在
kksfbc - 負責找到合適的子游標 或者創建一個新的子游標
kksFindCursorstat
11g開始有大量函數需要用到Mutex了
SQL> select location from X$MUTEX_SLEEP_HISTORY;
LOCATION
—————————————-
kkslce [KKSCHLPIN2]
kksfbc [KKSCHLFSP2]
kglhdgn2 106
kglpin1 4
kglhdgn2 106
kglllal1 109
kglpin1 4
kglpndl1 95
kglpin1 4
kglpin1 4
kksfbc [KKSCHLFSP2]
kglhdgn1 62
kglpnal1 90
kglllal3 111
kglpnal1 90
kglpnal1 90
kglget2 2
kglllal3 111
kglget2 2
kglobld1 75
kkslce [KKSCHLPIN2]
kglpndl1 95
kglpndl1 95
kglpin1 4
kkslce [KKSCHLPIN2]
kglpin1 4
kglget2 2
kglllal1 109
kgllkc1 57
kglget2 2
kglpnal1 90
kglpin1 4
kglpin1 4
kglpin1 4
kgllkdl1 85
kglllal3 111
kgllldl2 112
kglpin1 4
kglpndl1 95
kkslce [KKSCHLPIN2]
kksLockDelete [KKSCHLPIN6]
kglpndl1 95
kkslce [KKSCHLPIN2]
kglpnal1 90
kglpin1 4
kglpin1 4
kgllldl2 112
kgllkdl1 85
kglpin1 4
kglhdgn2 106
kglhdgn2 106
kksLockDelete [KKSCHLPIN6]
kglhdgn1 62
Mutex的Get和Sleep
當一個Mutex被申請時, 一般稱為一個get request。 若初始的申請未能得到授權, 則該進程會因為此次申請而進入到255次SPIN中(255是在代碼中用常量寫死的),每次SPIN循環迭代過程中該進程都會去看看Mutex被釋放了嗎。
若該Mutex在SPIN之后仍未被釋放,則該進程針對申請的mutex進入對應的mutex wait等待事件中。 實際進程的等待事件和等待方式由mutex的類型鎖決定,例如 Cursor pin、Cursor Parent。 舉例來說,這種等待可能是阻塞等待,也可以是sleep。
但是請注意在V$MUTEX_SLEEP_*視圖上的sleep列意味著等待的次數。相關代碼函數在開始進入等待時自加這個sleep字段。
等待計時從進程進入等待前開始計算等待時間, 當一個進程結束其等待,則等待的時間加入都總和total中。 該進程再次嘗試申請之前的Mutex,若該Mutex仍不可用,則它再次進入spin/wait的循環。
V$MUTEX_SLEEP_HISTORY視圖的GETS列僅在成功申請到一個Mutex時才增加。
短期持有一個mutex: spin 循環255次一般可以有效以S mode獲得一個mutex, 前提是該Mutex 已經被以S mode持有。 簡單來說若有2個進程同時以S mode去申請一個Mutex,則稍晚的一個申請者需要進入SPIN并等稍早一點的申請者完成它的例如創建針對該mutex的一個reference的操作,但這都是非常迅速的操作。
長期持有一個Mutex: 如若一個Mutex已經被某進程以X mode持有, 則往往有其進程以SHRD模式去申請該mutex時仍發現該mutex 以X mode被其他進程所持有,則往往這個EXCL 持有是 LONG_EXCL(可以通過SSD DUMP發現),則后續的申請者往往要進入spin循環,甚至需要等待
上面我講了willing-to-wait的mutex, 實際上mutex 的申請也可以是 nowait的。進程以nowait申請mutex時不會進入spin-cycle也不sleep,它只繼續常規處理。 當一個nowait get失敗時,將增加一次miss,但是實際上V$MUTEX_SLEEP_*中記錄的miss不是這樣的miss, 視圖中記錄的miss是等待的次數, 對于真正的miss沒有統計項。
Wait Time等待時間
類似于latch,spin time 不算做mutex的消耗時間,它只包含等待消耗的時間。
真正理解Mutex相關的等待
Mutex數據結構中存放了Holder id持有者ID , Ref Count,和其他Mutex相關的統計信息。 Holder id對應于持有該Mutex的session id (v$session.sid) 。 特別注意, Ref Count是進程并發以S mode參考該Mutex的進程數量(如下文的演示)。
當一個Mutex被以X mode 持有,則Holder id 為對應持有該mutex的session id,而Ref Count為0。
每一個共享S mode持有者僅僅增加mutex上的Ref Count。 可供大量session并發以S mode持有參考一個Mutex。 但是注意更新ref count的操作是串行的, 這是為了避免錯漏并維護mutex中正確的ref count。
下面我們詳細介紹一個執行游標過程中對mutex share pin的過程:
某進程以SHRD 模式申請一個Mutex,并嘗試臨時修改該Mutex的Holder ID
若該Mutex正被他人更新,則該session會將Holder id設置為本session的sid,之后該進程將增加ref count,之后再清楚mutex上的Holder id。簡單來說 這個Holder id是真正做了并行控制的功能。 若該Holder id 被設置了,則說明該Mutex要么被以EXCL模式持有,要么正有一個其他進程在以S mode申請該Mutex的過程中(例如更新Ref Count)。 當更新Ref Count時臨時設置holder id的目的就是為了實現避免其他進程并發更新該Mutex的機制。 通過這些例子說明了 , Mutex既可以用作Latch并發控制, 也可用作pin。
原文轉自:http://blogread.cn/it/article/6410