重點:DDL是保護表結構定義的。
當DDL命令發出時,Oracle會自動在被處理的對象上添加DDL鎖定,從而防止對象被其餘用戶所修改。當DDL命令結束之後,則釋放DDL鎖定。
DDL鎖定不能顯式的被請求,只有當對象結構被修改或者被引用時,纔會在對象上添加DDL鎖定。
並非全部DDL都會觸發DDL鎖,例如如今的建立索引語句,就只會獲取一個S模式的TM鎖,所以不會阻塞讀。而online模式建立索引的語句則只會獲取一個2號的TM鎖,所以連DML也不會被阻塞。
須要注意的是DDL總會提交,即使是執行不成功也是如此,所以若是在事務中執行了DDL語句會致使全部事物被提交。驗證很容易,在一個窗口執行一條delete而後執行DDL,你會發現記錄被不可逆轉的刪除了,RollBack無效。所以針對事務中的DDL請務必使用自治事務實現。
DDL鎖有3種:
2.1 排他DDL鎖 --即6號的TM鎖(Exclusive DDL Locks)
通常對錶的DDL語句都會獲取一個X模式的TM鎖,這是爲何在表結構更改時只能查詢不能修改的緣由。
2.2 共享DDL鎖(Share DDL Locks)
共享DDL鎖的常見情形爲建立存儲過程時,會嘗試爲全部涉及到的表添加共享DDL鎖,這會容許相似的DDL操做併發,但會阻止全部想要獲取排他DDL鎖的會話(即更改表結構的會話)。
--我覺的能夠認爲這就是4號的TM表鎖。
2.3 可中斷解析鎖(Breakable Parse Locks)
會話解析一條SQL或PLSQL代碼塊時,對於該語句引用的每個對象都會施加解析鎖,目的在於:若是以某種方式刪除或修改了引用對象,能夠將共享池中已經解析的緩存語句無效刷出。
之因此叫作可中斷解析鎖,是由於這種鎖優先級很低可能會被其餘互斥DDL操做打斷。
每一個SQL在解析時都會獲取一個可中斷解析鎖,只要SQL語句還在shared pool中,這個鎖就一直存在。
Library cache lock 和 Library cache pin就是屬於可中斷解析鎖,lock是針對父遊標句柄和子游標句柄的保護體,pin是針對父子游標的保護體。前者有三種模式:1 null,2 S,3 X 後者只有2 S,3 X兩種模式。
Latches:
可譯做閂或者栓,這是一種很是低級別的序列化結構,用於協調併發會話對於共享數據結構、文件等的訪問。
閂能夠防止併發會話破壞共享的內存資源,幾個很是典型的場景是:
- 多個會話同時修改數據
- 讀取的數據正在被其餘會話修改
- 從新分配內存
可能在這裏會和事務鎖混淆,但事務鎖是鎖定邏輯結構的,如表和行,可是閂倒是鎖定物理結構的,如內存中的數據塊、執行計劃鏈表等等。多個會話對於同一個對象的訪問就須要閂來保護了,例如對於同一個數據塊中不一樣行的訪問就須要latch來保護,而閂的存在時間是極短的,所以能夠實現高併發(其實Oracle高併發並不是是真正的併發而是latch釋放速度極快的串行訪問)。
一般在SGA中一個latch能夠保護多個對象,例如DBWn和LGWR進程從SGA中分配內存以便建立新的數據結構,爲了防止衝突進程會使用一種叫作shared pool latch的閂來序列化分配操做,在內存分配完畢後其它進程可能會須要訪問shared pool中的其餘區域如library cache,此時閂只會鎖住library cache而非整個shared pool。
一般狀況下oracle進程獲取閂的時間極短,一個簡單的查詢都會有成千上萬次的閂的獲取和釋放,是徹底不能由用戶控制的。
閂的數目的增多,意味着併發量增大,能夠經過v$latch視圖來查看閂的使用狀況,包括每種閂被請求和等待的次數。
Mutex:(Mutual exclusion object)
能夠譯做互斥體,這種結構很相似於閂,區別在於一種mutex只保護一種對象,而一種閂一般會保護多種對象。
mutex的優點在於:
- mutex能夠減小latch爭用
- mutex比latch佔用更少的內存
- share mode模式的mutex容許多個會話併發使用
其餘內部鎖:
這些是比mutex和latch更復雜的結構,oracle數據庫使用如下幾種內部鎖:
1.Dictionary cache locks
2.File and log management locks
3.Tablespace and undo segment locks
這幾種鎖的解釋有興趣能夠到官網看,平時基本觀察不到,後兩種基本都在多實例時出現。
拓展說明:
上邊談到了Library cache lock和Library cache
pin,這裏稍微解釋下:
1、首先咱們以Oracle 10.2以前版本做爲基準來解釋:主要來自於《Oracle8i Internal Services》一書的第四章
****************************************
Library cache的包含不少cache部分,它包含PLSQL代碼塊的、解析樹、SQL執行計劃等,它還包含一個由SQL引用的DIANA的數據庫對象,此對象被用於進行PLSQL塊的編譯以及SQL解析和執行,儘管數據字典中也包含此類信息。此外library cache也包含例如同義詞轉換、依賴追蹤等信息,固然還有library cache lock/pin等內存閂鎖。
Library cache lock和Library cache
pin屬於可中斷解析鎖,Library cache lock有NULL、S、X三種模式,Library cache pin有S和X兩種模式,在解析SQL時會話獲取S模式的Library cache lock,解析完畢後轉爲NULL模式。若是有DDL操做更改了語句涉及的數據庫對象,那麼依賴於此數據庫對象的全部library cache objects都會失效,失效過程就是失去NULL模式的library cache lock的過程。
****************************************
接下來先放一張圖:
這是library cache中主鏈表的簡易結構圖,每一個hash bucket對應一個父遊標句柄的鏈表,LCO表示library cache objects,是父遊標或者子游標。父子游標是一對一或者一對多的關係。
在瞭解了以上基本常識的狀況下,再來看涉及的內存栓鎖:
進行硬解析的會話須要獲取library cache latch(只有獨佔模式,無隊列)來生成父遊標句柄,待添加X模式library cache lock後釋放library cache latch進行父遊標句柄構造,構造父遊標句柄完畢後獲取X模式的library cache pin來構造父遊標,接下來獲取X模式的library cache lock生成子游標句柄,最後獲取X模式library cache pin構造子游標完成硬解析。
若是是在已經存在的父遊標上進行硬解析那麼就會添加S模式的父遊標句柄library cache
lock來獲取X模式的父遊標library cache pin,以後獲取X模式的library cache lock/pin完成硬解析。
軟解析時則先獲取S模式的父遊標句柄library cache lock,而後獲取S模式父遊標library cache
pin、S模式子游標句柄library cache lock和S模式子游標library cache pin。
2、接下來討論10.2以後的的變化:
library cache pin結構被Cursor:xxx類型的mutex取代,而在11.1以後library cache latch結構也被library cache:mutex xxx類型的mutex取代了。
那麼全新的SQL硬解析時首先會在library cache:mutex X的保護下獲取X模式的library cache lock,而後釋放mutex並構造父遊標句柄,以後獲取Cursor:pin X構造父遊標,而後獲取子游標句柄library cache lock構造子游標句柄並釋放父遊標的Cursor:pin X,最後獲取Cursor:pin X完成子游標的構造從而完成硬解析。
若是是已經存在的父遊標進行硬解析,那麼首先在library cache:mutex X的保護下獲取S模式的library
cache lock,以後獲取Cursor:pin S來pin住父遊標,而後獲取X模式的library cache lock構造子游標句柄並釋放父遊標mutex,最後獲取Cursor:pin X構造子游標完成硬解析。
若是是軟解析那麼首先在library
cache:mutex X的保護下獲取S模式的library cache lock,以後獲取Cursor:pin S來pin住父遊標,最後依次找到子游標句柄和子游標。
若是發生了Cursor:pin S wait on X,那麼意味着有硬解析在發生,而且可能存在較高的version count,致使此父遊標句柄下的全部遊標沒法拿到Cursor:pin S。還有一種狀況是遊標涉及的LCO發生了DDL致使全部句柄失效,此時須要進行從新編譯獲取X模式的子游標mutex,所以其餘會話發生Cursor:pin S wait on X等待。
一樣的library cache lock等待也意味着存在硬解析,只有硬解析纔會獲取X模式的library cache lock,因爲library cache lock的獲取須要mutex的保護,相應的mutex等待也會伴生,多是library cache:mutex X或者Cursor:xxx類型的mutex,這取決於library
cache lock的等待是在父遊標句柄仍是子游標句柄上,子游標句柄較爲常見。
最後重要說明:
以上全部觀點除來自書本的那段以外,都是基於buffer cache鏈表的查找方式進行類推解釋的,都是基於latch/mutex是鎖獲取與釋放的保護體來解釋的,都是基於修改底層結構須要在上層添加X模式鎖來解釋的,都是基於mutex是一種極端稀缺的資源來解釋的,極可能是錯的,我這裏只是爲了創建初步的架構方便理解,就算是錯的對我來講也無所謂。
總結一下本身的觀點:
DML和除可中斷解析鎖以外的DDL鎖就是保護邏輯結構的結構體,而library cahce lock/pin、latch和mutex則是保護內存中物理結構的結構體,拋開DML鎖,通常來講在內存中獲取內存鎖都須要latch和mutex的保護,常見的場景就是library cache中Library cache lock的獲取須要library cache:mutex X的保護,以及Buffer pool中的buffer pin 須要cbc latch保護住hash bucket中涉及到本SQL的鏈表頭。
從名字上就能夠看出latch和mutex的保護對象,cursor: xxx這種mutex保護的是遊標, cbc latch保護的則是cache buffer chain鏈表,library cahce:mutex(之前叫library cache latch)則是用於保護library cache的,具體說來也是hash bucket的父遊標句柄鏈表,以此來獲取parent cursor handler上的library cache lock。
Oracle官網已經沒有太多更詳細的關於內部閂鎖的資料,更詳細的關於內部latch和mutex的運做機制和種類,參考呂海波《Oracle內核技術揭祕》和Steve Adams的《Oracle 8i Internal Services》一書。