oracle為dml操作自動獲取行鎖和表鎖,操作的型別決定了鎖的行為,下面對dml操作鎖的情況作了乙個彙總:
sql statement
row locks
table lock mode
rs
rx
s
srx
x
select ... from table...
——noneyy
yyyinsert into table ...
yessxyy
nnnupdate table ...
yessx
y(注)
y(注)nn
nmerge into table ...
yessxyy
nnndelete from table ...
yessx
y(注)
y(注)nn
nselect ... from tableforupdateof ...
yessx
y(注)
y(注)nn
nlock table tablein ...——
row share mode ss
yyyy
nrow exclusive mode sx
yynn
nshare mode s
ynyn
nshare row exclusive mode
ssxyn
nnnexclusive mode x
nnnn
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語句修改的行,但不能看到其它事務未提交的改變。
原子操作和鎖
原子操作 在多程序 執行緒 的作業系統中不能被其它程序 執行緒 打斷的操作就叫原子操作,檔案的原子操作是指操作檔案時的不能被打斷的操作。原子操作是不可分割的,在執行過程中不會被任何其它任務或事件中斷。linux核心提供了一系列函式來實現核心中的原子操作,這些函式又分為兩類,分別針對位和整型變數進行原...
oracle鎖表操作
selectb.username,b.sid,b.serial logon time from v locked object a,v session b wherea.session id b.sid order by b.logon time altersystem kill session 8...
鎖 原子操作和golang mutex原始碼詳解
對於某一塊 段,多個執行緒或者協程同時執行會產生一些不符合預期的結果,就需要使用訊號量保護這一段 區,只能由乙個執行緒來占用和執行這段 這相當於是乙個大型的原子操作,由軟體層面來實現 下面是一段結果不符合預期的 段 var count 0 func main wg.add 2 go add wg g...