Oracle多粒度封鎖機制研究2
1.1.1v$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 |
鎖模式,取值同表三中的LMODE; |
表五:v$locked_object檢視欄位說明
1.2監控指令碼
根據上述系統檢視,可以編制指令碼來監控資料庫中鎖的狀況。
1.2.1showlock.sql
第一個指令碼showlock.sql,該指令碼透過連線v$locked_object與all_objects兩檢視,顯示哪些物件被哪些會話鎖住:
/* showlock.sql */
column o_name format a10
column lock_type format a20
column object_name format a15
select rpad(oracle_username,10) o_name,session_id sid,
decode(locked_mode,0,'None',1,'Null',2,'Row share',
3,'Row Exclusive',4,'Share',5,'Share Row Exclusive',6,'Exclusive') lock_type,
object_name ,xidusn,xidslot,xidsqn
from v$locked_object,all_objects
where v$locked_object.object_id=all_objects.object_id;
1.2.2showalllock.sql
第二個指令碼showalllock.sql,該指令碼主要顯示當前所有TM、TX鎖的資訊;
/* showalllock.sql */
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_type,request,ctime,block
from v$lock
where TYPE IN('TX','TM');
2Oracle多粒度封鎖機制示例
以下示例均執行在Oracle 8.1.7上,資料庫版本不同,其輸出結果也可能有所不同。首先建立3個會話,其中兩個(以下用SESS#1、SESS#2表示)以SCOTT使用者連入資料庫,以操作Oracle提供的示例表(DEPT、EMP);另一個(以下用SESS#3表示)以SYS使用者連入資料庫,用於監控;
2.1操作同一行資料引發的鎖阻塞
SESS#1:
SQL> select * from dept for update;
DEPTNO DNAMELOC
---------- -------------- -------------
10 account70
20 research8
30 sales8
40 operations8
SESS#3:
SQL> @showlock
O_NAMESID LOCK_TYPEOBJECT_NAMEXIDUSN XIDSLOT XIDSQN
---------- ----- --------------- --------------- ------ ------- ------
SCOTT17 Row shareDEPT 825861
SQL> @showalllock
SID TYID1ID2 LOCK_TYPEREQUESTCTIMEBLOCK
----- -- ---------- ---------- --------------- ---------- ---------- ----------
17 TX5242905861 Exclusive07610
17 TM329700 Row share07610
如第一個指令碼showlock所示,執行完SELECT…FOR UPDATE語句後,SESS#1(SID為17)在DEPT表上獲得Row share鎖;如第二個指令碼showalllock所示,SESS#1獲得的TX鎖為Exclusive,這些都驗證了上面的理論分析。另外,我們可以將TX鎖的ID1按如下方法進行分解:
SQL> select trunc(524290/65536) xidusn,mod(524290,65536) xidslot from dual;
XIDUSN XIDSLOT
------ -------
82
分解結果與第一個指令碼直接查出來的XIDUSN與XIDSLOT相同,而TX鎖的ID2(5861)與XIDSQN相同,可見當LOCK TYPE為TX時,ID1實際上是該事務所佔用的回滾段段號與事務表中的槽(SLOT)號的組合,ID2即為該槽被重用的次數,而這三個值實際上可以唯一地標識一個事務,即TRANSACTION ID,這三個值從系統表v$transaction中也可查到。
另外,DEPT表中有4條記錄被鎖定,但TX鎖只有1個,這也與上面的理論分析一致。繼續進行操作:
SESS#2:
SQL> update dept set loc=loc where deptno=20;
該更新語句被阻塞,此時再檢視系統的鎖情況:
SESS#3:
SQL> @showlock
O_NAMESID LOCK_TYPEOBJECT_NAMEXIDUSN XIDSLOT XIDSQN
---------- ----- --------------- --------------- ------ ------- ------
SCOTT17 Row shareDEPT 825861
SCOTT19 Row ExclusiveDEPT 000
SQL> @showalllock
SID TYID1ID2 LOCK_TYPEREQUESTCTIMEBLOCK
----- -- ---------- ---------- --------------- ---------- ---------- ----------
17 TX5242905861 Exclusive034621
17 TM329700 Row share034620
19 TM329700 Row Exclusive070
19 TX5242905861 None670
在DEPT表上除了SESS#1(SID為17)持有Row share鎖外,又增加了SESS#2(SID為19)持有的Row Exclusive鎖,但還沒有為SESS#2分配回滾段(XIDUSN、XIDSLOT、XIDSQN的值均為0);而從第二個指令碼看到,SESS#2的TX鎖的LOCK_TYPE為None,其申請的鎖型別(REQUEST)為6(即Exclusive),而其ID1、ID2的值與SESS#1所持有的TX鎖的ID1、ID2相同,SESS#1的TX鎖的阻塞域(BLOCK)為1,這就說明了由於SESS#1持有的TX鎖,阻塞了SESS#2的更新操作(SESS#2所更新的行與SESS#1所鎖定的行相沖突)。還可以看出,SESS#2先申請表級的TM鎖,後申請行(事務)級的TX鎖,這也與前面的理論分析一致。
下面,將SESS#1的事務進行回滾,解除對SESS#2的阻塞,再對系統進行監控。
SESS#3:
SQL> @showlock
O_NAMESID LOCK_TYPEOBJECT_NAMEXIDUSN XIDSLOT XIDSQN
---------- ----- --------------- --------------- ------ ------- ------
SCOTT19 Row ExclusiveDEPT 2105803
SQL> @showalllock
SID TYID1ID2 LOCK_TYPEREQUESTCTIMEBLOCK
----- -- ---------- ---------- --------------- ---------- ---------- ----------
19 TX1310825803 Exclusive01570
19 TM329700 Row Exclusive03330
可以看到,SESS#1的事務所持有的鎖已經釋放,系統為SESS#2的事務分配了回滾段,而其TX鎖也已經獲得,並且ID1、ID2是其真正的Transaction ID。再將會話2的事務進行回滾。
SESS#2:
SQL> rollback;
Rollback complete.
檢查系統鎖的情況:
SESS#3:
SQL> @showlock
no rows selected
SQL> @showalllock
no rows selected
可以看到,TM與TX鎖已全部被釋放。
2.2實體完整性引發的鎖阻塞
DEPT(部門)表有如下欄位DEPTNO(部門編號),DNAME(部門名稱),LOC(部門位置);其中DEPTNO列為主鍵。
SESS#1
SQL> INSERT INTO DEPT(DEPTNO) VALUES(50);
1 row created.
SESS#3
SQL> @showlock
O_NAMESID LOCK_TYPEOBJECT_NAMEXIDUSN XIDSLOT XIDSQN
---------- ----- --------------- --------------- ------ ------- ------
SCOTT7 Row ExclusiveDEPT 68829
SQL> @showalllock
SID TYID1ID2 LOCK_TYPEREQUESTCTIMEBLOCK
----- -- ---------- ---------- --------------- ---------- ---------- ----------
7 TX39330429 Exclusive060
7 TM35740 Row Exclusive060
向DEPT表中插入一條DEPTNO為50的記錄後,SESS#1(SID為7)在DEPT表上獲得Row Exclusive鎖,並且由於進行了資料插入,該事務被分配了回滾段,獲得TX鎖。
SESS#2
INSERT INTO DEPT(DEPTNO) VALUES(50);
這時,SESS#2(SID為8)也向DEPT表中插入一條DEPTNO為50的記錄,該語句被阻塞,檢查鎖情況:
SESS#3
SQL> @showlock
O_NAMESID LOCK_TYPEOBJECT_NAMEXIDUSN XIDSLOT XIDSQN
---------- ----- --------------- --------------- ------ ------- ------
SCOTT8 Row ExclusiveDEPT 77530
SCOTT7 Row ExclusiveDEPT 68829
SQL> @showalllock
SID TYID1ID2 LOCK_TYPEREQUESTCTIMEBLOCK
----- -- ---------- ---------- --------------- ---------- ---------- ----------
7 TX39330429 Exclusive0921
7 TM35740 Row Exclusive0920
8 TX45882730 Exclusive0220
8 TM35740 Row Exclusive0220
8 TX39330429 None4220
SESS#2在DEPT表上也獲得了Row Exclusive鎖,同樣也獲得了回滾段的分配,得到TX鎖,但是由於其插入的記錄與SESS#1插入的記錄的DEPTNO均為50,該語句成功與否取決於SESS#1的事務是提交還是回滾,所以SESS#2被阻塞,表現為SESS#2以Share方式(REQUEST=4)等待SESS#1所持有的TX鎖的釋放。
這時,如果SESS#1進行回滾:
SESS#1
SQL> ROLLBACK;
Rollback complete.
SESS#2
1 row created.
SESS#3
SQL> @showlock
O_NAMESID LOCK_TYPEOBJECT_NAMEXIDUSN XIDSLOT XIDSQN
---------- ----- --------------- --------------- ------ ------- ------
SCOTT8 Row ExclusiveDEPT 77530
SQL> @showalllock
SID TYID1ID2 LOCK_TYPEREQUESTCTIMEBLOCK
----- -- ---------- ---------- --------------- ---------- ---------- ----------
8 TX45882730 Exclusive01360
8 TM35740 Row Exclusive01360
SESS#2的阻塞將被解除,SESS#2只持有原先已有的TM與TX鎖,其等待的TX鎖(由SESS#1持有)也消失了。
如果SESS#1提交而不是回滾,在SESS#2上將會出現如下提示:
ERROR at line 1:
ORA-00001: unique constraint (SCOTT.PK_DEPT) violated錯誤。
即發生主鍵衝突,SESS#1與SESS#2的所有鎖資源均被釋放。
2.3參照完整性引發的鎖阻塞
EMP(員工)表有如下欄位:EMPNO(員工編號),ENAME(員工姓名),DEPTNO(員工所在部門編號),其中DEPTNO列為外來鍵,其父表為DEPT。
SESS#1
SQL> insert into dept(deptno) values(60);
1 row created.
SESS#3
SQL> @showlock
O_NAMESID LOCK_TYPEOBJECT_NAMEXIDUSN XIDSLOT XIDSQN
---------- ----- --------------- --------------- ------ ------- ------
SCOTT7 Row ExclusiveDEPT 2633
SQL> @showalllock
SID TYID1ID2 LOCK_TYPEREQUESTCTIMEBLOCK
----- -- ---------- ---------- --------------- ---------- ---------- ----------
7 TX13107833 Exclusive01480
7 TM35740 Row Exclusive01480
SESS#1(SID為7)在DEPT表中先插入一條DEPTNO為60的記錄,SESS#1獲得了DEPT表上的Row Exclusive鎖,及一個TX鎖。
SESS#2
insert into emp(empno,deptno) values(2000,60);
被阻塞
SESS#3
SQL> @showlock
O_NAMESID LOCK_TYPEOBJECT_NAMEXIDUSN XIDSLOT XIDSQN
---------- ----- --------------- --------------- ------ ------- ------
SCOTT7 Row ExclusiveDEPT 2633
SCOTT8 Row ExclusiveEMP32031
SQL> @showalllock
SID TYID1ID2 LOCK_TYPEREQUESTCTIMEBLOCK
----- -- ---------- ---------- --------------- ---------- ---------- ----------
7 TX13107833 Exclusive02281
7 TM35740 Row Exclusive02280
8 TX19662831 Exclusive090
8 TM35760 Row Exclusive090
8 TX13107833 None490
SESS#2(SID為8)向EMP表中出入一條新記錄,該記錄DEPT值為60(即SESS#1剛插入,但還未提交的記錄的DEPTNO值),SESS#2獲得了EMP表上的Row Exclusive鎖,另外由於插入記錄,還分配了回滾段及一個TX鎖,但由於SESS#2的插入語句是否成功取決於SESS#1的事務是否進行提交,所以它被阻塞,表現為SESS#2以Share(REQUEST=4)方式等待SESS#1釋放其持有的TX鎖。這時SESS#1如果提交,SESS#2的插入也將執行成功,而如果SESS#1回滾,由於不符合參照完整性,SESS#2將報錯:
SESS#2
insert into emp(empno,deptno) values(2000,60)
*
ERROR at line 1:
ORA-02291: integrity constraint (SCOTT.FK_DEPTNO) violated - parent key not
Found
SESS#2持有的鎖也被全部釋放。
2.4外來鍵未加索引引發的鎖阻塞
EMP表上的DEPTNO列為外來鍵,但沒有在該列上建索引。
SESS#1
SQL> delete emp where 0=1;
0 rows deleted.
SESS#3:
SQL> @showlock
O_NAMESID LOCK_TYPEOBJECT_NAMEXIDUSN XIDSLOT XIDSQN
---------- ----- --------------- --------------- ------ ------- ------
SCOTT7 Row ExclusiveEMP000
SQL> @showalllock
SID TYID1ID2 LOCK_TYPEREQUESTCTIMEBLOCK
----- -- ---------- ---------- --------------- ---------- ---------- ----------
7 TM35760 Row Exclusive0100
首先SESS#1(SID為7)做了一個刪除操作,但由於條件(0=1)為永假,所以實際上並沒有一行被刪除,從監控指令碼可以看出SESS#1在EMP表上獲得Row Exclusive鎖,但由於沒有實際的行被刪除,所以並沒有TX鎖,也沒有為SESS#1分配回滾段。
SESS#2:
SQL> delete dept where 0=1;
該語句雖然也不會刪除實際資料,但卻被阻塞,檢視系統的鎖情況:
SESS#3:
SQL> @showlock
O_NAMESID LOCK_TYPEOBJECT_NAMEXIDUSN XIDSLOT XIDSQN
---------- ----- --------------- --------------- ------ ------- ------
SCOTT8 NoneEMP000
SCOTT7 Row ExclusiveEMP000
SQL> @showalllock
SID TYID1ID2 LOCK_TYPEREQUESTCTIMEBLOCK
----- -- ---------- ---------- --------------- ---------- ---------- ----------
7 TM35760 Row Exclusive0311
8 TM35760 None4120
SESS#2申請在EMP表上加SHARE鎖(REQUEST=4),但該申請被SESS#1阻塞,因為SESS#1已經在EMP表上獲得了Row Exclusive鎖,與SHARE鎖不相容。
下面我們對SESS#1進行回滾後,再進行監控。
SESS#3:
SQL> @showlock
O_NAMESID LOCK_TYPEOBJECT_NAMEXIDUSN XIDSLOT XIDSQN
---------- ----- --------------- --------------- ------ ------- ------
SCOTT8 ShareEMP000
SCOTT8 Row ExclusiveDEPT 000
SQL> @showalllock
SID TYID1ID2 LOCK_TYPEREQUESTCTIMEBLOCK
----- -- ---------- ---------- --------------- ---------- ---------- ----------
8 TM35740 Row Exclusive0160
8 TM35760 Share0160
SESS#2在EMP表上獲得Share鎖後,又在DEPT表上獲得Row Exclusive鎖,由於沒有實際的行被修改,SESS#2並沒有獲得TX鎖。
在Oracle8中,如果子表的外來鍵上沒有加索引,當在父表上刪除記錄時,會先在子表上申請獲得Share鎖,之後再在父表上申請Row Exclusive鎖。由於表級Share鎖的封鎖粒度較大,所以容易引起阻塞,從而造成效能問題。
當在外來鍵上建立索引後,在父表上刪除資料將不再對子表上加Share鎖,如下所示:
SESS#1:
SQL> create index i_emp_deptno on emp(deptno);
Index created.
SQL> delete dept where 0=1;
0 rows deleted.
SQL>
SQL> @showlock
O_NAMESID LOCK_TYPEOBJECT_NAMEXIDUSN XIDSLOT XIDSQN
---------- ----- --------------- --------------- ------ ------- ------
SCOTT7 Row ExclusiveDEPT 000
SQL> @showalllock
SID TYID1ID2 LOCK_TYPEREQUESTCTIMEBLOCK
----- -- ---------- ---------- --------------- ---------- ---------- ----------
7 TM35740 Row Exclusive090
可以看到,在EMP表DEPTNO列上建立索引後,在DEPT表上執行DELETE操作,不再要求在EMP表上加Share鎖,只是在DEPT表上加Row Exclusive鎖,封鎖的粒度減小,引起阻塞的可能性也減小。
3Oracle多粒度封鎖機制總結
Oracle透過具有意向鎖的多粒度封鎖機制進行併發控制,保證資料的一致性。其DML鎖(資料鎖)分為兩個層次(粒度):即表級和行級。通常的DML操作在表級獲得的只是意向鎖(RS或RX),其真正的封鎖粒度還是在行級;另外,在Oracle資料庫中,單純地讀資料(SELECT)並不加鎖,這些都極大地提高了系統的併發程度。
在支援高併發度的同時,Oracle利用意向鎖及資料行上加鎖標誌位等設計技巧,減小了Oracle維護行級鎖的開銷,使其在資料庫併發控制方面有著明顯的優勢。
[@more@]來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/18921899/viewspace-1016707/,如需轉載,請註明出處,否則將追究法律責任。
相關文章
- Oracle多粒度封鎖機制研究1Oracle
- Oracle多粒度封鎖機制研究(zt)Oracle
- Oracle多粒度封鎖機制研究二(zt)Oracle
- oracle鎖機制研究Oracle
- Oracle鎖機制Oracle
- oracle 鎖機制Oracle
- MySQL鎖(樂觀鎖、悲觀鎖、多粒度鎖)MySql
- ORACLE鎖機制-轉載Oracle
- oracle中的鎖機制Oracle
- ORACLE DML鎖定機制Oracle
- ORACLE鎖機制深入理解Oracle
- JAVA多執行緒與鎖機制Java執行緒
- ORACLE 鎖機制及解決方法Oracle
- oracle封鎖測試Oracle
- Java多執行緒4:synchronized鎖機制Java執行緒synchronized
- oracle工作機制(2)Oracle
- ORACLE 資料庫中的鎖機制Oracle資料庫
- oracle的鎖和並行機制薦Oracle並行
- Oracle的鎖機制歸納總結Oracle
- PHP 鎖機制PHP
- SQLite鎖機制SQLite
- Mysql鎖機制MySql
- java鎖機制Java
- SQL鎖機制SQL
- oracle deadlock 之(一)--鎖機制介紹Oracle
- ORACLE的工作機制-2Oracle
- PostgreSQL 併發控制機制(2):表級鎖和行級鎖SQL
- Oracle回收站表閃回機制研究Oracle
- Java 細粒度鎖續篇Java
- Oracle資料庫封鎖和select...[for update [of tab.col]]的研究Oracle資料庫
- 轉貼:Oracle的鎖機制歸納總結Oracle
- Oracle資料庫資料鎖機制解析(zt)Oracle資料庫
- Mysql鎖機制分析MySql
- Enqueue 鎖定機制ENQ
- MS SQL鎖機制SQL
- mysql的鎖機制MySql
- 分散式鎖機制分散式
- MONGODB 讀寫佇列增高與寫延遲與多粒度鎖MongoDB佇列