Oracle-11g中的併發控制(2012/11/16)
1 事務基礎
在DB中,可能出現如下3種現象
髒讀 | 在事務中,讀到了其它事務沒有提交的記錄 |
不可重複讀 | 在事務中,即使查詢條件相同,下次返回的記錄與上次返回記錄不一樣,不一樣體現在記錄被修改或記錄被刪除 |
幻影讀 | 在事務中,即使查詢條件相同,下次返回的記錄與上次返回記錄不一樣,不一樣體現在新增加了記錄。 |
SQL92規定的事務隔離級別如下表。
oracle支援3種事務隔離級別:read-only/readcommitted/serializable。其中read-only不屬於SQL92,readcommitted是oracle的預設隔離級別。
2 oracle中併發控制
2.1 多版本併發控制
在undo segment中保留了歷史資料,也就是說記錄可能有多個版本,版本用SCN(systemchange manage)來識別。SCN是事務提交後系統為之分配的一個全域性唯一的事務ID。undo segment中的資料有3種功能:便於事務回滾,提供讀一致性,支援flashback。
查詢語句被啟動的同時獲取當前的SCN,DB只會返回SCN小於當前SCN的記錄。多版本併發控制技術使得讀不阻塞寫,寫不阻塞讀,從而大大的提高了系統的併發性。【多個版本的資料是儲存在undo segment中】
2.2 oracle支援的讀一致性
oracle支援兩個級別的讀一致性。語句級讀一致性和事務級讀一致性。oracle天生支援語句級讀一致性,只有隔離級別在serializable時支援事務級讀一致性。
●語句級讀一致性
讀到的資料集和查詢啟動時的結果集是一樣的。也就是說,不存在髒讀,也不會讀到查詢啟動之後其它事務提交的資料(包括update/delete/insert)。
●事務級讀一致性
概念和serializable是一致的。
2.3 oracle中的鎖
2.3.1 上鎖的時機以及持續時間
上鎖發生在語句級別,解鎖發生在事務級別。即提交事務或回滾時釋放鎖,事務開始時不會獲取鎖,而是在執行過程中,若語句需要才會上鎖。
2.3.2 鎖的型別
●DML鎖即data鎖,保護資料
●DDL鎖即dictionary鎖,保護物件的定義
●內部鎖和latch,保護內部的資料結構,比如資料檔案
2.3.3 DML鎖
2.3.3.1行鎖
當事務需要修改某個記錄時,需要獲取這個記錄對應的行鎖。在執行update/delete/insert/select…for udpate時,獲取行鎖。
實際上,一個行鎖可能對應多個記錄。即行鎖是一個粗粒度的鎖,其開銷不大,所以系統不會控制單個事務被上鎖的記錄的數量。
【理解】其實oracle不需要細化到一個記錄的鎖。比如,T1事務現在需要修改記錄R,但是此時記錄R已經被事務T2上鎖,T1需要等待T2被提交或回滾是才能操作記錄R,T2被被提交或回滾涉及到的記錄是所有被T2修改過的記錄。
2.3.3.2表鎖
DDL和DML都需要表鎖。在DML操作中需要獲取表鎖的語句有insert/delete/update/select…forupdate/lock table.
表是由行組成的,當我們向某個表加鎖時,一方面需要檢查該鎖的申請是否與原有的表級鎖相容;另一方面,還要檢查該鎖是否與表中的每一行上的鎖相容。比如一個事務要在一個表上加 S 鎖,如果表中的一行已被另外的事務加了 X 鎖,那麼該鎖的申請也應被阻塞。如果表中的資料很多,逐行檢查鎖標誌的開銷將很大,系統的效能將會受到影響。為了解決這個問題,可以在表級引入新的鎖型別來表示其所屬行的加鎖情況,這就引出了“意向鎖”的概念。意向鎖的含義是如果對一個結點加意向鎖,則說明該結點的下層結點正在被加鎖;對任一結點加鎖時,必須先對它的上層結點加意向鎖。如:對錶中的任一行加鎖時,必須先對它所在的表加意向鎖,然後再對該行加鎖。這樣一來,事務對錶加鎖時,就不再需要檢查表中每行記錄的鎖標誌位了,系統效率得以大大提高。
鎖有兩種基本的鎖型別(S鎖、X 鎖),可以自然地派生出兩種意向鎖:
意向共享鎖(Intent Share Lock,簡稱 IS 鎖):如果要對一個數據庫物件加S鎖,首先要對其上級結點加IS 鎖,表示它的後裔結點擬(意向)加 S鎖;
意向排它鎖(Intent Exclusive Lock,簡稱 IX 鎖):如果要對一個數據庫物件加X 鎖,首先要對其上級結點加 IX鎖,表示它的後裔結點擬(意向)加X 鎖。
另外,基本的鎖型別(S、X)與意向鎖型別(IS、IX)之間還可以組合出新的鎖型別,理論上可以組合出4種,即:S+IS,S+IX,X+IS,X+IX,但稍加分析不難看出,實際上只有 S+IX 有新的意義,其它三種組合都沒有使鎖的強度得到提高(即:S+IS=S,X+IS=X,X+IX=X,這裡的“=”指鎖的強度相同)。所謂鎖的強度是指對其它鎖的排斥程度。
這樣我們又可以引入一種新的鎖的型別共享意向排它鎖(SharedIntent Exclusive Lock,簡稱 SIX 鎖) :如果對一個數據庫物件加 SIX 鎖,表示對它加 S 鎖,再加IX 鎖,即 SIX=S+IX。例如:事務對某個表加 SIX 鎖,則表示該事務要讀整個表(所以要對該表加S 鎖),同時會更新個別行(所以要對該表加 IX
鎖)。這樣資料庫物件上所加的鎖型別就可能有5 種:即S、X、IS、IX、SIX。
具有意向鎖的多粒度封鎖方法中任意事務 T 要對一個數據庫物件加鎖,必須先對它的上層結點加意向鎖。申請封鎖時應按自上而下的次序進行;釋放封鎖時則應按自下而上的次序進行;具有意向鎖的多粒度封鎖方法提高了系統的併發度,減少了加鎖和解鎖的開銷。
Oracle的 DML鎖(資料鎖)正是採用了上面提到的多粒度封鎖方法,其行級鎖雖然只有一種(即X鎖),但其 TM鎖(表級鎖)型別共有5種,分別稱為共享鎖(S鎖)、排它鎖(X 鎖)、行級共享鎖(RS鎖)、行級排它鎖(RX 鎖)、共享行級排它鎖(SRX 鎖),與上面提到的S、X、IS、IX、SIX 相對應。
各個鎖的意義如下:【個人理解,有待驗證】
RS鎖 | 表示事務要讀取表的少量記錄 |
RX鎖 | 表示事務要修改表的少量記錄 |
S鎖 | 表示事務要讀取表的絕大部分記錄 |
SRX鎖 | 表示事務要讀取表的絕大部分記錄 並且需要修改少量記錄 |
X鎖 | 表示事務要修改表的絕大部分記錄 或者需要修改表的定義 |
各個粒度的鎖的相容性如下:
【理解】
進行DML操作只會獲取RX粒度的表鎖,由於RX之間是相容和的,所以DML之間在表鎖層次是不會相互阻塞的。進行DDL操作時獲取X鎖(個人猜測)。因為讀操作不需枷鎖,為什麼還需要S/RS/SRX粒度的表鎖?答案是為使用者自己控制並行性提供條件。
2.3.4 DDL鎖
用於保護物件的定義,使用者不能顯示的獲得。事務會對其涉及到物件新增DDL鎖,從而避免在操作物件資料的過程中物件被刪除或定義被修改。DDL鎖分為3個型別
Exclusive DDL lock | DDL需要修改物件的定義時需要獲取此鎖。在這種情況下,DDL也會獲取表鎖(應該是X鎖)。 |
Shared DDL lock | 比如在create procdure過程中需要此鎖 |
Breakable DDL lock | 在shared SQL area中,儲存了已經解析並優化過的SQL語句,這些SQL語句是和物件(比如table/view)相關聯,若關聯的物件的定義改變,那麼在shared SQL area對應的SQL語句就失效了。 在物件的定義發生變化後,Breakable DDL lock用來通知shared sql area刪除對應的SQL項。 |
2.3.5 內部鎖和latch
latch是輕量級鎖。用於保護SGA共享的資料結構。
2.3.10 鎖轉換和鎖提升(Data LockConversion Versus Lock Escalation)
鎖轉換 | 改變鎖的嚴格程度,比如把 S鎖轉換為X鎖 |
鎖升級 | 改變鎖的粒度,比如把行鎖變為表鎖 |
因為鎖升級大大的提升了死鎖的概率,所以oracle從來不會進行鎖升級。
2.3.11 死鎖
oracle會自動檢測死鎖,發生死鎖後,回滾其中的一個事務的當前語句。應用如何避免死鎖?各個事務按照相同的順序處理資料。