oracle鎖機制研究

alei_1304發表於2013-05-31

oracle鎖機制研究


不同於其他資料庫,oracle提供了行級鎖,在保證資料一致性的情況下極大的提高了併發訪問的效率

oracle提供了三中鎖模式
Null  主要用於對資料字典物件的訪問
Share 鎖持有者對資源進行只讀訪問,允許其他程式併發對資源只讀訪問
Exclusive 鎖持有者對資源進行修改,不允許其他進行對資源做任何訪問


對於行級鎖,oracle提供了TM鎖和TX鎖來分別保護表和被修改的資料行

(一)TX鎖用於保護當前修改的資料行不被其他併發訪問的事務所修改

開啟一個會話,修改資料
--會話1
SQL> update t set seq=10 where seq=10;

1 row updated.
我們開啟另外一個會話,也修改同一資料行
會話2
SQL> update t set seq=10 where seq=10;
沒有任何反應,被阻塞
查詢會話等待事件

SQL> select w.SID,w.EVENT from v$session_wait w where w.WAIT_CLASS<>'Idle';

       SID EVENT
---------- ----------------------------------------------------------------
        48 enq: TX - row lock contention
可以看到會話2被TX鎖阻塞,等待TX鎖的釋放
處理會話1
SQL> commit;
Commit complete.
再觀察一下會話2
SQL> update t set seq=10 where seq=10;
1 row updated.
再次進行查詢等待時間,發現等待時間消失。
進一步驗證了TX主要用來保護資料行不被其他併發訪問的事務所修改

(二)TM鎖:TM鎖用於在併發事務訪問過程中保護表的結果,TM鎖共有以下五種模式
1、行級排他鎖(RX鎖)
我們進行DML操作更新表的資料或者顯示執行lock table * in row exclusive mode,都會在對應的表上加行級排他鎖(RX鎖)
該鎖定模式允許其他事務修改資料表中的其他資料行,也允許其他併發事務在該表上加RX鎖,
但是不允許在該表上加S和X模式的鎖
會話1
SQL> lock table t in row exclusive mode;
Table(s) Locked.
會話2
SQL> lock table t in row exclusive mode;
Table(s) Locked.
SQL> lock table t in share mode;
同樣在該表上加share模式的鎖也產生等待
通過等待事件查詢如下:
SQL> select w.SID,w.EVENT from v$session_wait w where w.WAIT_CLASS<>'Idle';

       SID EVENT
---------- ----------------------------------------------------------------
        10 enq: TM - contention
等待獲得TM鎖的釋放
2、行級共享鎖(RS鎖)
通常是通過select … from for update語句新增的,同時該方法也是我們用來手工鎖定某些記錄的主要方法。比如,當我們在查詢某些記錄的過程中,
不希望其他使用者對查詢的記錄進行更新操作,則可以發出這樣的語句。當資料使用完畢以後,直接發出commit或者rollback命令將鎖定解除。
當表上新增了RS鎖定以後,不允許其他事務對相同的表新增排他鎖(RX,X,SRX),允許其他事務對錶增加RS,S鎖,也允許其他的事務通過DML語句或lock命令鎖定相同表裡的其他資料行。
會話1
SQL> select * from t where seq=10 for update;

       SEQ
----------
        10
會話2

SQL> select * from t where seq=10 for update;
產生了等待,同樣是等待TM鎖的釋放
會話1

SQL> lock table t in row share mode;
Table(s) Locked.
會話2
SQL> lock table t in row share mode;
Table(s) Locked.
SQL> lock table t in share mode;
Table(s) Locked.
執行以下三個語句都產生了等待
SQL> lock table t in exclusive mode;
SQL> lock table t in row exclusive mode;
SQL> lock table t in share row exclusive mode;
3、共享鎖(S鎖)
通過lock table * in share mode對錶增加共享鎖,不允許併發事務更新該表,也不允許併發對該表增加排他型別的鎖(X,RX,SRX),但允許共享模式索引該表(S,RS)
允許其他使用者以select * from  .. for update鎖定該表
會話1
SQL> lock table t in share mode;
Table(s) Locked.
會話2

SQL> lock table t in share mode;
Table(s) Locked.
SQL> lock table t in row share mode;
Table(s) Locked.
新增以下三種模式的鎖都產生了等待
SQL> lock table t in exclusive mode;
SQL> lock table t in row exclusive mode;
SQL> lock table t in share row exclusive mode;
同樣不允許更新該表資料
SQL> update t set seq=10 where seq=1;
4、排他鎖(X)
通過lock table .. in exclusive mode,對錶增加拍他鎖,這時對該表不能做DML操作,只能做查詢,同樣不允許併發事務對該表新增任何型別的鎖
會話1
SQL> lock table t in exclusive mode;
Table(s) Locked.
其他併發會話的以下所有操作都產生等待
SQL> lock table t in share mode;
SQL> lock table t in row share mode;
SQL> lock table t in share row exclusive mode;
SQL> lock table t in exclusive mode;
SQL> update t set seq=10 where seq=1;
都在等待TM鎖的釋放
5、共享行級排他鎖(SRX)
可以通過lock table .. in share row exclusize mode對錶加SRX鎖,可以對該表加RS鎖,同樣併發事務不能對該表加任何模式的鎖,
會話1
SQL> lock table t in exclusive mode;
Table(s) Locked.
會話2的以下操作都產生等待
SQL> lock table t in share row exclusive mode;
SQL> lock table t in share mode;
SQL> lock table t in row exclusive mode;
SQL> update t set seq=10 where seq=1;
這五種TM相容關係如下
-   S   X   RS  RX  SRX  
S   √   ×   √   ×   ×    
X   ×   ×   ×   ×   ×    
RS  √   ×   √   √   √    
RX  ×   ×   √   √   ×    
SRX ×   ×   √   ×   ×   
對Oracle資料庫中的各SQL語句所產生的表級鎖的情況進行彙總,如下表所示:
SQL語句                            表鎖定模    允許的表鎖定模式  
Select * from ……                    RS      RS、RX、S、SRX、X  
Insert into ……                      RX          RS、RX  
Update ……                           RX          RS、RX  
Delete from ……                      RX          RS、RX  
Select * from for update            RS          RS、RX、S、SRX  
lock table in row share mode        RS          RS、RX、S、SRX  
lock table in row exclusive mode      RX      RS、RX  
lock table in share mode          S       RS、S  
lock table in share row exclusive mode  SRX     RS  
lock table in exclusive mode        X        
對於通過lock table命令主動新增的鎖定來說,如果要釋放它們,只需要發出rollback命令即可。
(三)單例項下oracle鎖的型別
根據保護的物件不同,Oracle資料庫鎖可以分為以下幾大類:DML鎖(data locks,資料鎖),用於保護資料的完整性;DDL鎖(dictionary locks,字典鎖),
用於保護資料庫物件的結構,如表、索引等的結構定義;內部鎖和閂(internal locks and latches),保護資料庫的內部結構。
當Oracle執行DML語句時,系統自動在所要操作的表上申請TM型別的鎖。當TM鎖獲得後,系統再自動申請TX型別的鎖,並將實際鎖定的資料行的鎖標誌位進行置位。
這樣在事務加鎖前檢查TX鎖相容性時就不用再逐行檢查鎖標誌,而只需檢查TM鎖模式的相容性即可,大大提高了系統的效率
(四)與鎖相關的檢視

1、v$lock檢視
      v$lock檢視列出當前系統持有的或正在申請的所有鎖的情況,其主要欄位說明如下:

欄位名稱

型別

說明

SID

NUMBER

會話(SESSION)標識;

TYPE

VARCHAR(2)

區分該鎖保護物件的型別;

ID1

NUMBER

鎖標識1;

ID2

NUMBER

鎖標識2;

LMODE

NUMBER

鎖模式:0(None),1(null),2(row share), 3(row exclusive),4 (share),5(share row exclusive),6(exclusive)

REQUEST

NUMBER

申請的鎖模式:具體值同上面的LMODE

CTIME

NUMBER

已持有或等待鎖的時間;

BLOCK

NUMBER

是否阻塞其它鎖申請;0未阻塞 1 阻塞

在rac環境下,block欄位值還會多一個數值2,表示rac環境下節點間潛在的鎖申請。

兩個節點各有一個程式申請鎖

節點1

SQL> update t set t.seq=10 where seq=10

1 row updated.

SQL> select * from gv$lock  where type='TX';

   INST_ID ADDR     KADDR           SID TY        ID1        ID2      LMODE    REQUEST      CTIME      BLOCK
---------- -------- -------- ---------- -- ---------- ---------- ---------- ---------- ---------- ----------
         1 322E2C84 322E2DA0        120 TX     655365        165          6          0          7          2

雖然其他節點並沒有修改這一行資料,但是仍然存在block為2的潛在鎖申請。

節點2修改這一行資料

SQL> update t set seq=10 where seq=10;

產生等待。

SQL> select * from gv$lock  where type='TX';

   INST_ID ADDR     KADDR           SID TY        ID1        ID2      LMODE    REQUEST      CTIME      BLOCK
---------- -------- -------- ---------- -- ---------- ---------- ---------- ---------- ---------- ----------

         2 343BAB70 343BAB84        132 TX     524312        230          0          6         59          0
         1 322E2C84 322E2DA0        120 TX     524312        230          6          0        187          2

已經有了全域性鎖申請,但是block欄位沒有變化。

 

 

其中在TYPE欄位的取值中,本文只關心TM、TX兩種DML鎖型別;

關於ID1、ID2,TYPE取值不同其含義也有所不同:

TYPE

ID1

ID2

TM

被修改表的標識(object_id)

0

TX

以十進位制數值表示該事務所佔用的回滾段號與該事務在該回滾段的事務表(Transaction table)中所佔用的槽號(slot number,可理解為記錄號)。其組成形式為: 0xRRRRSSSS ( RRRR = RBS number, SSSS = slot )。

以十進位制數值表示環繞(wrap)次數,即該槽(slot)被重用的次數;

2、v$locked_object檢視

v$locked_object檢視

v$locked_object檢視列出當前系統中哪些物件正被鎖定,其主要欄位說明如下:

欄位名稱

型別

說明

XIDUSN

NUMBER

回滾段號;

XIDSLOT

NUMBER

槽號;

XIDSQN

NUMBER

序列號;

OBJECT_ID

NUMBER

被鎖物件標識;

SESSION_ID

NUMBER

持有鎖的會話(SESSION)標識;

ORACLE_USERNAME

VARCHAR2(30)

持有該鎖的使用者的Oracle使用者名稱;

OS_USER_NAME

VARCHAR2(15)

持有該鎖的使用者的作業系統使用者名稱;

PROCESS

VARCHAR2(9)

作業系統的程式號;

LOCKED_MODE

NUMBER

鎖模式,取值同v$lock檢視的LMODE;


3、dba_blockers和dba_waiters檢視雖。

為了方便我們查詢會話的阻塞狀態,當前會話被那個會話阻塞,哪些會話處於被阻塞,oracle提供dba_blockers和dba_waiters檢視,為了能夠訪問這兩個檢視,需要執行 $ORACLE_HOME/rdbms/admin/catblock.sql.舉例如下

會話1

SQL> update t set seq=10 where seq=10;

會話2

SQL>update t set seq=20 where seq=20;

回到會話1

SQL>update t set seq=20 where seq=20;

會話1被會話2阻塞,通過查詢這兩個檢視

SQL> select * from dba_blockers;

HOLDING_SESSION
       ---------------
             25

只有一列,記錄了哪些session持有tx鎖導致其他會話阻塞,當前查詢得知sid=25的會話阻塞了其他會話持有tx鎖

進一步查詢dba_waiters可以查詢到哪個會話被sid=25的會話阻塞

SQL> SQL> select WAITING_SESSION,HOLDING_SESSION from dba_waiters;

WAITING_SESSION HOLDING_SESSION
--------------- ---------------
             28              25

sid=28的會話被sid=25的會話阻塞,我們可以通過

alter system kil session '25,1'

清除25會話之後,發現兩個檢視中對應記錄消失。

當然只是比較簡單的情況,具體的生產環境會比較複雜,需要通過關聯v$session檢視來進一步檢視具體的會話資訊,連線資訊以便及時監控,並聯系應用開發人員處理。

 

 

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

相關文章