Oracle鎖的一些實驗與技術知識

regonly1發表於2009-06-28

下面回顧一下為解決前面觸發器死鎖問題所碰到過的知識:
1、Oracle鎖資訊檢視:v$lock
主要欄位含義:
kaddr -> v$session.lockwait
type    ->鎖型別,除系統本身的鎖外,我們只要關注TX/TM/UL三種。而UL是使用者自定義的鎖,通常關注度不大。所以只剩下TX和TM兩種。
TX是一種行級鎖,通常以一個事務為單位的形式存在,也就是說並不是若干行被鎖住了就出現若干個TX行級鎖。
SQL> conn scott/tiger;
已連線。
SQL> select * from dept;
    DEPTNO DNAME          LOC
---------- -------------- -------------
        10 ACCOUNTING00   NEW YORK
        20 RESEARCH       DALLAS
        30 SALES          CHICAGO
        40 OPERATIONS     BOSTON

SQL> select * from salgrade;

     GRADE      LOSAL      HISAL
---------- ---------- ----------
         1        700       1200
         2       1201       1400
         3       1401       2000
         4       2001       3000
         5       3001       9999

SQL> update dept d set d.dname = d.dname || '00' where d.deptno = 10;

已更新 1 行。

SQL> select * from v$lock l where l.type in('TX','TM');

ADDR     KADDR           SID TY        ID1        ID2      LMODE    REQUEST      CTIME      BLOCK
-------- -------- ---------- -- ---------- ---------- ---------- ---------- ---------- ----------
67B92964 67B92A70         12 TX      65543       3265          6          0          3          0
67B4E074 67B4E088         12 TM      30137          0          3          0          3          0

SQL> update salgrade s set s.losal = s.losal + 10 where s.grade=1;

已更新 1 行。

SQL> select * from v$lock l where l.type in('TX','TM');

ADDR     KADDR           SID TY        ID1        ID2      LMODE    REQUEST      CTIME      BLOCK
-------- -------- ---------- -- ---------- ---------- ---------- ---------- ---------- ----------
67B92964 67B92A70         12 TX      65543       3265          6          0         18          0
67B4E0F8 67B4E10C         12 TM      30142          0          3          0          3          0
67B4E074 67B4E088         12 TM      30137          0          3          0         18          0
從以上實驗可以看出
 第一次update dept表的時候就出現了一個TX鎖,另一個TM鎖表示的是鎖定的物件(dept)。
此時對應的ID1就是對應的object_id(v$lock.type='TM'時)。
 第二次update salgrade表的時候,出現了兩個TM鎖,因為此時鎖定了兩個物件(dept和salgrade)。
但是,對應的TX鎖卻還是隻有一個。
 為什麼第二次明明鎖定了兩行,卻只有一個鎖呢?這是由於實際TX鎖並不是真正意義上的行級鎖,而是事務級的。相面這段話是引用funyucat寫的《Oracle多粒度封鎖機制研究》中的一段話:
TX的本義是Transaction(事務),當一個事務第一次執行資料更改(Insert、Update、Delete)或使用SELECT… FOR UPDATE語句進行查詢時,它即獲得一個TX(事務)鎖,直至該事務結束(執行COMMIT或ROLLBACK操作)時,該鎖才被釋放。所以,一個TX鎖,可以對應多個被該事務鎖定的資料行。(在我們用的時候多是其一個事務,然後SELECT… FOR UPDATE NOWAIT)這段話讓我少走了不少彎路,我一直在追求能夠從v$lock中獲取每行鎖定標識的蹤影。從這裡發現我這個想法是不現實的。
 這點從v$session表裡面也可以看出。雖然v$session表有記錄鎖表資訊的四個欄位:
 row_wait_obj#
 row_wait_file#
 row_wait_block#
 row_wait_row#
 (注:這個四個欄位分別對應了rowid的四個組成資訊:即object_id、relative_fileno、block_number、row_number。
 不過這裡需要注意的一點是row_id中的object_id實際上是指user_object中的data_object_id。這點在轉換的時候需要注意。)
 但是實際上這裡指的是最後一次鎖定的行的資訊。並不是查詢到當時所有鎖定行的資訊。 這點很重要,直接導致了不能找到這些鎖定行的資訊。
SQL> select s.SID, ta.deptno, o.object_name, ta.rowid
  2   from v$session s, dept ta, user_objects o, v$locked_object lo
  3  where lo.SESSION_ID = s.SID
  4    and lo.OBJECT_ID = o.object_id
  5    and dbms_rowid.rowid_object(ta.rowid) = o.data_object_id
  6    and o.object_id = s.ROW_WAIT_OBJ#
  7    and dbms_rowid.rowid_relative_fno(ta.rowid) =  s.ROW_WAIT_FILE#
  8    and dbms_rowid.rowid_block_number(ta.rowid) = s.ROW_WAIT_BLOCK#
  9    and dbms_rowid.rowid_row_number(ta.rowid) = s.ROW_WAIT_ROW#;

       SID     DEPTNO   OBJECT_NAME     ROWID
   ---------- ---------- ---------------------------  --------------------------------------------------
        13         10  DEPT   AAAHW5AABAAAMUSAAA

sid欄位:指的是當前所在session的id,即v$session.sid
id1/id2欄位:
id1欄位上面已經提到過,當v$lock.type='TM'的時候,id1欄位指的就是object_id。類似資訊也可以從v$locked_object中找到:
SQL> desc v$locked_object;
 名稱                                                  是否為空? 型別
 ----------------------------------------------------- -------- ------------------------------------
 XIDUSN                                                         NUMBER
 XIDSLOT                                                        NUMBER
 XIDSQN                                                         NUMBER
 OBJECT_ID                                                      NUMBER
 SESSION_ID                                                     NUMBER
 ORACLE_USERNAME                                                VARCHAR2(30)
 OS_USER_NAME                                                   VARCHAR2(30)
 PROCESS                                                        VARCHAR2(12)
 LOCKED_MODE                                                    NUMBER
 這個表對應有xidusn、xidslot、xidsqn的資訊,這個可以跟v$transaction表對應的欄位進行關聯。
這三個欄位可以在v$lock.type='TX'的時候換算得到:
xidusn=(id1/65536)
xidslot=mod(id1,65536)
xidsqn=id2

lmode及block欄位:
lmode這個欄位顯示了鎖定的模式:
鎖模式:0(None),1(null),2(row share), 3(row exclusive),4 (share),5(share row exclusive),6(exclusive)
share是指共享鎖(select等)。exclusive是指排他鎖(update/delete/select ...for update(nowait)/)。
通常共享鎖可以多個鎖定(都為s鎖),且不能加x鎖。
而排他鎖則是單個鎖定(x鎖),不能再加其他鎖。
block欄位顯示當前鎖是否阻塞了其他鎖:
0, 未阻塞其他程式;
1, 阻塞了其他程式;
2, 'Global', /* This lock is global, so we can't tell */
當lmode>0且block=1時即表明該表處於死鎖狀態,也就是說當時真鎖定了一行記錄,但同時又阻塞了其他程式,下面一條記錄顯示了死鎖的情況:

SQL> select * from v$lock l where l.type in('TM','TX');

ADDR     KADDR           SID TY        ID1        ID2      LMODE    REQUEST      CTIME      BLOCK
-------- -------- ---------- -- ---------- ---------- ---------- ---------- ---------- ----------
67BA143C 67BA1548         10 TX     393255       4314          6          0         81          1
................

已選擇6行。

當發生死鎖後,Oracle會自動解鎖(>9ir1),並提示“等待資源時檢測到死鎖”
SQL> update dept d set d.dname = d.dname || '00' where d.deptno = 10;

已更新 1 行。

SQL> update salgrade s set s.losal = s.losal + 10 where s.grade=1;
update salgrade s set s.losal = s.losal + 10 where s.grade=1
*
ERROR 位於第 1 行:
ORA-00060: 等待資源時檢測到死鎖
自動解鎖後,剛才的blcok=1及lmode>0的情況消失。

另外兩個欄位:
ctime:Time since current mode was granted
request:
Lock mode in which the process requests 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)
--大於0時,表示當前會話被阻塞,其它會話佔有改鎖的模式

以上是關於v$lock檢視的一些欄位說明。另外也涉及到了v$session、v$locked_object等檢視的資訊。

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

相關文章