鎖相關基礎知識

leon830216發表於2014-03-16
1. 鎖型別
latch鎖: 保護記憶體結構, chain, 鏈
lock 鎖: 保護 buffer, block | 排他鎖 (X), 共享鎖 (S)

2. 行級鎖
由 DML 語句產生, 資料行的所標記指向事務槽

3. 事務鎖 (TX)
一個事務修改多行也之會產生一個事務鎖
由行級鎖產生, commit 或 rollback 解鎖, 不影響讀 (產生 CR 塊)

4. 表級鎖 (TM)
即行級排他鎖 RX 鎖 (Row exclusive)
當進行 DML 時, 會自動在被更新的表上新增 RX 鎖, 也可以執行 lock 命令顯式的在表上新增 RX 鎖
允許其他事務透過 DML 語句修改相同表裡的其他資料行
允許其他事務使用 lock 命令對錶新增 RX 鎖定
不允許其他事務對錶新增 X 鎖

4-1. 行級共享鎖 (Row Shared, 簡稱 RS 鎖)
select * from t for update

4-2. 共享鎖 (Share, 簡稱 S 鎖)
lock table t in share mode

4-3. 排他鎖 (Exclusive, 簡稱 X 鎖)
lock table t in exclusive mode

4-4. 共享行級排他鎖 (Share Row Exclusive, 簡稱 SRX 鎖)
lock table t in share row exclusive mode

5. 檢視
5-1. v$transaction
select xid,xidusn,xidslot,xidsqn,ubafil,ubablk,status from v$transaction;

xid: 事務ID
xidusn: 表示當前事務使用的回滾段的編號xidslot: 說明該事務在回滾段頭部的事務表中對應的記錄編號(也可以叫做槽號) 
xidsqn: 說明序列號
status: 說明該事務是否為活動的
ubafil: 該事務對應的最後(新)的回滾塊資料檔案
ubablk: 該事務對應的最後(新)的回滾塊號

5-2. v$lock
記錄了會話已經獲得的鎖定以及正在請求的鎖定的資訊
SID: 會話的ID號
TYPE: 鎖定鎖定級別
LMODE: 已經獲得的鎖定的模式, 以數字編碼表示
REQUEST: 正在請求的鎖定的模式, 以數字編碼表示
BLOCK: 是否阻止了其他使用者獲得鎖定, 大於 0 說明是, 等於 0 說明否

鎖定模式                鎖定簡稱 編碼數值
Row Exclusive           RX       3
Row Shared              RS       2
Share                   S        4
Exclusive               X        6
Share Row Exclusive     SRX      5
NULL                    N/A      0 或者 1

select sid,type,id1,id2,
decode(lmode,0,'None',1,'Null',2,'Row share',3,'Row Exclusive',4,'Share',5,'Share Row Exclusive',6,'Exclusive') lock_mode,
decode(request,0,'None',1,'Null',2,'Row share',3,'Row Exclusive',4,'Share',5,'Share Row Exclusive',6,'Exclusive') request_mode,
block
from v$lock where sid=159;

獲取鎖定與被鎖定的會話
select
    (select username from v$session where sid=a.sid) blocker,a.sid,' is blocking ',
    (select username from v$session where sid=b.sid) blockee,b.sid
from v$lock a,v$lock b
where a.block = 1 and b.request > 0 and a.id1 = b.id1 and a.id2 = b.id2;

對於 TM 鎖來說, ID1 表示被鎖定的物件的物件ID, ID2 始終為 0
對於 TX 鎖來說, ID1 表示事務使用的回滾段編號以及在事務表中對應的記錄編號, ID2 表示該記錄編號被重用的次數
將 ID1 拆解
select trunc(393249/power(2,16)) as undo_blk#,bitand(393249,to_number('ffff','xxxx')) + 0 as slot# from dual;

5-3. v$enqueue_lock
該檢視中包含的欄位以及欄位含義與 v$lock 中的欄位一模一樣
該檢視中只顯示那些申請鎖定, 但是無法獲得鎖定的會話資訊
記錄按照申請鎖定的時間先後順序排列, 先申請鎖定的會排在前面, 排在前面的會話將會先獲得鎖定

select a.sid blocker_sid,a.serial#,a.username as blocker_username,b.type,
decode(b.lmode,0,'None',1,'Null',2,'Row share',3,'Row Exclusive',4,'Share',5,'Share Row Exclusive',6,'Exclusive') lock_mode,
b.ctime as time_held,c.sid as waiter_sid,
decode(c.request,0,'None',1,'Null',2,'Row share',3,'Row Exclusive',4,'Share',5,'Share Row Exclusive',6,'Exclusive') request_mode,
c.ctime time_waited
from v$lock b, v$enqueue_lock c, v$session a
where a.sid = b.sid and b.id1= c.id1(+) and b.id2 = c.id2(+) and c.type(+) = 'TX' and  b.type = 'TX' and b.block = 1
order by time_held, time_waited;

alter system kill session '129,10910';

5-4. v$locked_object
記錄了當前已經被鎖定的物件的資訊
XIDUSN: 當前事務使用的回滾段的編號
XIDSLOT: 該事務在回滾段頭部的事務表中對應的記錄編號
XIDSQN: 序列號
OBJECT_ID: 當前被鎖定的物件ID, 可以根據該 ID 號到 dba_objects 裡查詢被鎖定的物件名稱
LOCKED_MODE: 鎖定模式的數字編碼

select /*+ RULE */ /* ls.osuser os_user_name,*/ ls.username,ls.type,o.object_name,
decode(ls.lmode,1,null,2, 'Row Share',3,'Row Exclusive',4,'Share',5,'Share Row Exclusive',6,'Exclusive',null) lock_mode,
o.owner,ls.sid,ls.serial#,ls.id1,ls.id2
from dba_objects o,
(select s.osuser,s.username,l.type,l.lmode,s.sid,s.serial#,l.id1,l.id2 from v$session s,v$lock l where s.sid = l.sid) ls
where o.object_id = ls.id1 /* and o.owner <> 'SYS' */
order by o.owner, o.object_name;

5-5. v$session
記錄了當前所有會話的相關資訊
SID: 會話的編號
SERIAL#: 序列號
SID 和 SERIAL# 可以認為是 v$session 的主鍵, 它們共同唯一標識一個會話

6. 初始化引數
transactions: 資料庫整體能執行的並行活動事務總數 (可以獲得的 TX 鎖定的總個數)
dml_locks: 一個表上可以同時獲得的 TM 鎖總數
select name,value,description from v$parameter where name in('transactions','dml_locks');

select resource_name,current_utilization,max_utilization,initial_allocation
from v$resource_limit
where resource_name in('transactions','dml_locks');

7. 死鎖
在 Oracle中, 造成死鎖的那個 DML 語句會被撤銷, 死鎖總是由於應用程式設計不合理引起的
當某個會話的事務引起了死鎖時, Oracle 會自動將阻塞該事務的其他事務中相應的 DML 語句撤銷, 而阻塞該事務的其他事務中的其他 DML 語句並沒有撤銷

session 1
--
select sid from v$mystat where rownum=1;
update employees set last_name=last_name||'a' 
where employee_id=100

session 2
--
select sid from v$mystat where rownum=1;
update employees set last_name=last_name||'b' 
where employee_id=101;

session 1
--
update employees set last_name=last_name||'c' where employee_id=101;

session 2
--
update employees set last_name=last_name||'d' where employee_id=100;


來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/22558114/viewspace-1122582/,如需轉載,請註明出處,否則將追究法律責任。

相關文章