Oracle鎖2:DML操作和鎖,oracle鎖dml操作
Oracle為DML操作自動擷取行鎖和表鎖,操作的類型決定了鎖的行為,下面對DML操作鎖的情況作了一個匯總:
SQL Statement |
Row Locks |
Table Lock Mode |
RS |
RX |
S |
SRX |
X |
SELECT ... FROM table ... |
—— |
none |
Y |
Y |
Y |
Y |
Y |
INSERT INTO table ... |
Yes |
SX |
Y |
Y |
N |
N |
N |
UPDATE table ... |
Yes |
SX |
Y(注) |
Y(注) |
N |
N |
N |
MERGE INTO table ... |
Yes |
SX |
Y |
Y |
N |
N |
N |
DELETE FROM table ... |
Yes |
SX |
Y(注) |
Y(注) |
N |
N |
N |
SELECT ... FROM table FOR UPDATE OF ... |
Yes |
SX |
Y(注) |
Y(注) |
N |
N |
N |
LOCK TABLE table IN ... |
—— |
|
|
|
|
|
|
ROW SHARE MODE |
|
SS |
Y |
Y |
Y |
Y |
N |
ROW EXCLUSIVE MODE |
|
SX |
Y |
Y |
N |
N |
N |
SHARE MODE |
|
S |
Y |
N |
Y |
N |
N |
SHARE ROW EXCLUSIVE MODE |
|
SSX |
Y |
N |
N |
N |
N |
EXCLUSIVE MODE |
|
X |
N |
N |
N |
N |
N |
註:如果另一個事務和當前事務出現行衝突,則需要等待
下面闡述當行被查詢和修改時會涉及到的鎖。
當行被查詢時的鎖
一個查詢可以直接通過SELECT查詢資料,或者其它語句間接的查詢資料,如:INSERT、MERGE、UPDATE和DELETE,其中只有INSERT操作不是必定會涉及到查詢的。因為查詢僅讀資料,因此他們被其它DML語句幹涉的可能性是最小的。
如果查詢沒有FOR UPDATE子句,則查詢時:
1)查詢不要求資料鎖,因此,其它事務能查詢和更新正在被查詢的資料;
2)查詢不必等待任何資料鎖被釋放,因此,查詢總是能執行。一個例外是查詢必須等待分散式交易的一些特定的資料鎖。
當行被修改時的鎖
一些資料庫使用一個記憶體中的列表來維護鎖,但Oracle資料庫儲存鎖資訊在資料區塊中,資訊包含了被鎖的行,每個行鎖僅影響一行資料。
Oracle資料庫為行鎖的擷取使用了一個隊列機制,如果一個事務請求一個行鎖,並且行未被鎖,那麼事務擷取行的資料區塊的一個鎖,事務自身會在資料區塊頭的interested transaction list(ITL)地區放一個條目,被事務修改的每一行都指向ITL中儲存的事務ID的一個拷貝,因此,被單個事務修改的在同一塊中的100行資料會要求100個行鎖,但是所有100行都引用同一個事務ID。
當事務結束時,事務ID保留在資料區塊頭的ITL地區中。如果一個新的事物想修改一行,那麼它使用事務ID判斷該鎖是否是啟用的,如果鎖是啟用的,那麼新事務的session會請求在鎖被釋放時被通知,否則,新事務擷取鎖。
INSERT、UPDATE、DELETE和SELECT ... FOR UPDATE將滿足:
1)使用這些DML操作的事務將在修改的行上請求排它行鎖,因此,其它事務不能更新或者刪除鎖定的行,直到事務commit或者roll back;
2)除了行鎖,使用這些DML操作的事務至少需要請求一個子排它表鎖(subexclusive table lock,SX)。如果事務已經擁有了一個S、SRX或者X表鎖(比SX鎖有更強的限制),那麼SX鎖不被需要;如果事務已經擁有了一個SS鎖,那麼Oracle資料庫自動轉換SS鎖到SX鎖;
3)除非涉及的行被修改,事務不會對任何子查詢或者隱含的子查詢涉及的行加行鎖;例如下面的update操作,使用那個了一個子查詢(括弧中的部分)和隱含子查詢(WHERE a > 5):
UPDATE t SET x = ( SELECT y FROM t2 WHERE t2.z = t.z ) WHERE a > 5;
事務將不會對子查詢(SELECT y FROM t2 WHERE t2.z = t.z)涉及的行加鎖。
4)在同一個事務中,一個查詢能看到先前的DML語句修改的行,但不能看到其它事務未提交的改變。