本文結合示例簡要的介紹了一下Oracle中鎖的機制。
為了解決多用戶環境下並發操作相同的資源而造成的錯誤修改數據的問題。單用戶環境下不需要考慮鎖,因為所有操作都是串行的。下面的文章簡要的介紹了一下
鎖的分類異常復雜,enqueue、latch、mutex等,都是為了解決並發存在的,自己也有些混亂,所以也不過多解釋了。下面列舉一些對於lock的要點內容。
l 排他鎖:
不允許相關的資源被共享。一個資源在一個時間點內只有一個事務能夠獲取該資源的排他鎖,只有持有該鎖的事務能夠修改相關的資源,
其他想要獲取鎖的事務只能等待該事務因為commit或者rollback而釋放排他鎖。
l 共享鎖:
允許相關的資源被共享。也就是說允許多個事務同時持有某個資源的共享鎖。
對於一個dml操作,會對表以及行加鎖,也就是v$lock中的TM鎖和TX鎖。
l 行級鎖基本原理:
行級鎖的信息是置於數據塊中的,如果要修改某一條記錄的值,其實就是在訪問相應的block,並且分配一個ITL,然後通過rowid訪問
rowpiece header ,如果第二個字節lock byte(lock byte只占用1個字節,最大值為255,這也是為什麼maxtrans最大為255)為0,則將其改為分配的ITL slot number。另外一個事務如果也想要修改數據,就會發現lock byte不為0,如果第一個事務還沒有結束,則第二個事務進入enqueue等待,也就是transaction enqueue。
關於transaction enqueue有一個很有趣的例子,事務不一定是按照時間的先後順序進行的。
具體地址在:
http://docs.oracle.com/cd/E11882_01/server.112/e25789/transact.htm#autoId12
l 對於Table lock來說可以分為以下幾種類型:
1. Row Share (RS|SS)
2. Row Exclusive Table Lock (RX|SX)
3. Share Table Lock (S)
4. Share Row Exclusive Table Lock (SRX|SSX)
5. Exclusive Table Lock (X)
以下是v$lock.LMODE字段中的數字對應的鎖類型
LMODE(Lockmode in which the session holds the lock):
0 -none
1 -null (NULL)
2 -row-S (SS)
3 -row-X (SX)
4 -share (S)
5 -S/Row-X (SSX)
6 -exclusive (X)
為了更好的開展下面的內容,這裡列舉一下各種TM鎖類型的兼容情況。
詳細驗證情況會在4中給出。
RS|SS
RX|SX
S
SRX|SSX
X
RS|SS
√
√
√
√
×
RX|SX
√
√
×
×
×
S
√
×
√
×
×
SRX|SSX
√
×
×
×
×
X
×
×
×
×
×
順便引用一下經典內容:
只有被修改時,行才會被鎖定。
當一條語句修改了一條記錄,只有這條記錄上被鎖定,在Oracle數據庫中不存在鎖升級。
當某行被修改時,它將阻塞別人對它的修改。
當一個事務修改一行時,將在這個行上加上行鎖(TX),用於阻止其它事務對相同行的修改。
讀永遠不會阻止寫。
讀不會阻塞寫,但有唯一的一個例外,就是select ...for update。
寫永遠不會阻塞讀。
當一行被修改後,Oracle通過回滾段提供給數據的一致性讀
在11gr2中,可以使用insert /*+ append */ intoselect 的方式執行直接路徑加載。
或者 insert /*+append_values */ into values 的方式。
這裡使用第二種。
Session1session_id=22:
_dexter@FAKE>insert /*+ append_values */ into tun2_tab values (1) ;
1 rowcreated.
_dexter@FAKE>select sid , type , lmode , request , block from v$lock where sid = (select sidfrom v$mystat where rownum<2) ;
SID TYPE LMODE REQUEST BLOCK
-------------- ---------- ---------- ----------
22 AE 4 0 0
22 TM 6 0 0
22 TX 6 0 0
可以看到使用直接路徑加載的時候會對表加6級排他鎖。根據表1,它會阻塞所有試圖在表上加鎖的事務。
Session2session_id=24:
_dexter@FAKE>update tun2_tab set id=3 ;
waiting...
看一下鎖的情況:
_sys@FAKE>select sid , type , id1 , lmode , request , block
2 from v$lock l
3 where sid in (select session_id from v$locked_object)
4 and type in ('TM', 'TX')
5 order by 1 ;
SID TYPE ID1 LMODE REQUEST BLOCK
-------------- ---------- ---------- ---------- ----------
22 TM 82618 6 0 1 --session1 包含了表6級鎖,它正在阻塞其他的事務
22 TX 524296 6 0 0
24 TM 82618 0 3 0 --session2 它正在請求表的3級鎖。
Session1
Session2
Description
T1
insert /*+ append_values */ into tun2_tab values (1) ;