創(chuàng )建測試表
aaa@AAA.US.ORACLE.COM>create table test (a number,b number);
表已創(chuàng )建。
1 對于未提交的insert操作
aaa@AAA.US.ORACLE.COM>insert into test values(10,20);
已創(chuàng )建 1 行。
| SQL> select * from v$lock; |
可見(jiàn),對于未提交的insert操作,會(huì )產(chǎn)生兩個(gè)鎖,其類(lèi)型(TYPE)分別為T(mén)M和TX,也就是表級意向鎖和事務(wù)鎖.
表級意向鎖的模式(LMODE)為:3,表示是rowexclusive,即表示此表中的某行獲得了行排他鎖.
事務(wù)鎖的模式(LMODE)為:6, 表示是exclusive,即排他鎖,表示此事務(wù)獲得了排他鎖.
BLOCK表示此鎖是否阻塞了其它的鎖,即發(fā)生死鎖;此處沒(méi)有.
2 對于提交的insert操作
aaa@AAA.US.ORACLE.COM>commit;
提交完成。
SQL> select * from v$lock;
ADDR KADDR SID TYPE ID1 D2 LMODE REQUEST CTIME BLOCK
此處已沒(méi)有記錄,說(shuō)明在提交后,即完成了鎖的釋放.
3 對于未提交的update操作
aaa@AAA.US.ORACLE.COM>update test set a=11 where a=10;
已更新 1 行。
| SQL> select * from v$lock; |
可見(jiàn)update操作所引起的鎖的信息完全等同于insert操作..
4 對于提交的update操作
aaa@AAA.US.ORACLE.COM>commit;
提交完成。
| SQL> select * from v$lock; |
此處已沒(méi)有記錄,說(shuō)明在提交后,即完成了鎖的釋放.
5 對于select操作
| aaa@AAA.US.ORACLE.COM>select * from test where a=11; |
此處已沒(méi)有記錄,說(shuō)明select操作不會(huì )引起任何鎖.
這是與sql server等數據庫不同的,這些數據庫select操作也會(huì )引起鎖,以取得一致讀;
而oracle是通過(guò)回滾機制實(shí)現一致讀的,所以不需要引入鎖機制,這極大增強了oracle的并發(fā)度.
6 for update操作
| aaa@AAA.US.ORACLE.COM>select * from test for update; |
可見(jiàn),for update操作會(huì )引起兩個(gè)鎖,分別是表級意向鎖(TM)和事務(wù)鎖(TX);
表級意向鎖鎖定模式為:2(row share),這表示屬于此表中的某行獲得了共享鎖;相比較DML操作,此處鎖級別低了一級,DML的是3;其實(shí)在oracle中沒(méi)有行級共享鎖.
TX的鎖定模式為6,表示行級排他鎖,這與DML的效果一致.
7 for update操作:commit后
當commit后,就會(huì )發(fā)現鎖已被釋放.
8 for update與update互鎖問(wèn)題
1) session 1中:
| aaa@AAA.US.ORACLE.COM>select * from test for update; |
2) session 2中:
aaa@AAA.US.ORACLE.COM>update test set a=12 where a=11;
此時(shí),這條語(yǔ)句處于阻塞狀態(tài),說(shuō)明等待鎖;
查看鎖:
| SQL> select * from v$lock; |
發(fā)現有兩個(gè)會(huì )話(huà)處于有鎖的活動(dòng);
發(fā)出for update操作的session 1(sid=17)的有模式為2(row share)的行級共享意向表級鎖;模式為6(exclusive)行級排他鎖;
發(fā)出update操作的session 2(sid=16)的模式為3(row exclusive)的行級排他意向鎖;模式為0(None)的行級鎖;
這說(shuō)明,第二個(gè)session(sid=16)由于是后發(fā)出的操作,它會(huì )首先去檢索將要操作的表是否存在鎖,此處由于存在,故就堵塞了,所以沒(méi)有獲得行級鎖;
這也就說(shuō),兩個(gè)session在檢測操作對象是否處于被鎖狀態(tài)時(shí),是首先檢測其表級鎖,這就避免了去檢測沒(méi)一行的鎖,這就提升了性能.
像這里的情況,我們所操作的對象是行,但所利用的檢測鎖機制是在表級.
同時(shí),會(huì )發(fā)現session 1(sid=17)的TX鎖的BLOCK為1,這表示此鎖堵住了另外的鎖;同時(shí)我們會(huì )看到session 2(sid=16)的TX鎖等待的對象ID1和ID2與sid=16的相同,這說(shuō)明sid=17的堵住了sid=16的.
8 rollback第一個(gè)會(huì )話(huà)的for update操作
aaa@AAA.US.ORACLE.COM>rollback;
回退已完成。
查看鎖:
| SQL> select * from v$lock; |
可見(jiàn),第一鎖的信息已沒(méi)有.
此時(shí)只有session 2的鎖的信息;而且session2已獲得鎖.
如果再將session 2進(jìn)行回滾,就會(huì )發(fā)現session2的鎖也沒(méi)有了.
9實(shí)體完整性引發(fā)的鎖阻塞
在具有primary key約束的表中,在兩個(gè)session中插入同樣的記錄
aaa@AAA.US.ORACLE.COM>alter table test add constraint pk_aprimary key(a);
表已更改。
Session 1中:
aaa@AAA.US.ORACLE.COM>insert into test(a) values(101);
已創(chuàng )建 1 行。
Session 2中:
aaa@AAA.US.ORACLE.COM>insert into test(a) values(101);
session 2處于阻塞狀態(tài).
可見(jiàn),在session1沒(méi)有提交的情況,實(shí)體完整性約束就會(huì )阻塞住session 2;
查看鎖:
| SQL> select * from v$lock; |
可見(jiàn),session 1(sid=17)已獲得TM和TX鎖,并且阻塞住了其它的鎖;
session 2(sid=16)被阻塞,
可以發(fā)現, session 2已獲得了行排他鎖:
12AE60B0 12AE61BC 16 TX 458759 5513 6 0 164 0
已經(jīng)完全分配了新的事務(wù);所以session 2不是被堵在和session1競爭同一個(gè)數據塊上(如上面的例子),而是被堵在了完整行約束上:
132D2CCC 132D2CDC 16 TX 131081 5627 0 4 164 0
這個(gè)鎖請求的類(lèi)型為4 (share);
Sessio 1:
aaa@AAA.US.ORACLE.COM>rollback;
回退已完成。
Session 2:
aaa@AAA.US.ORACLE.COM>insert into test(a) values(101);
已創(chuàng )建 1 行。
| ADDR KADDR SID TYPE ID1 D2 LMODE REQUEST CTIME BLOCK |
可見(jiàn),session 2所持有的鎖剩余兩個(gè),那個(gè)原來(lái)等待session 1的鎖已釋放.
10參照完整性引發(fā)的鎖阻塞
aaa@AAA.US.ORACLE.COM>create table test_child(c number,a numbernot null constra
int pk_a_ref references test(a));
表已創(chuàng )建。
aaa@AAA.US.ORACLE.COM>insert into test(a) values(101);
已創(chuàng )建 1 行。
Session 1:
| aaa@AAA.US.ORACLE.COM>@showlockedobj |
可以發(fā)現,有兩個(gè)對象被鎖住: TEST和TEST_CHILD
| aaa@AAA.US.ORACLE.COM>@showlocks |
可見(jiàn)有三個(gè)鎖;
| SQL> select object_name from dba_objects where object_id=29512; |
可見(jiàn),除了TEST表需要的TM和TX鎖外,
還同時(shí)將TEST_CHILD表鎖住了:其鎖類(lèi)型為Rowshare
session 2:
aaa@AAA.US.ORACLE.COM>insert into test_child(c,a) values(11,101);
插入外鍵值為101的,語(yǔ)句的執行會(huì )停頓.
| aaa@AAA.US.ORACLE.COM>@showlockedobj |
這時(shí)會(huì )發(fā)現,被鎖住的對象有4個(gè);這是因為在子表中的插入同時(shí)會(huì )鎖住父表和子表.
| aaa@AAA.US.ORACLE.COM>@showlocks |
已選擇7行。
分析鎖的情況.
Session 2(sid=16)有四個(gè)鎖:分別是子表的TM和TX鎖:
16 TM 29515 0 Row Exclusive 0 79
0
16 TX 458770 5521 Exclusive 0 79
父表的TM和TX鎖:
16 TX 655381 5678 None 4 79
0
16 TM 29512 0 Row share 0 79
0
這是因為參照完整性需要父表在參照的過(guò)程中不能發(fā)生改變,所以要對父表加上這些限制.
Session 1:
aaa@AAA.US.ORACLE.COM>rollback;
回退已完成。
Session 2:
aaa@AAA.US.ORACLE.COM>insert into test_child(c,a) values(11,101);
insert into test_child(c,a) values(11,101)
*
ERROR 位于第 1 行:
ORA-02291: 違反完整約束條件 (AAA.PK_A_REF) - 未找到父項關(guān)鍵字
11 更新子表時(shí)
aaa@AAA.US.ORACLE.COM>update test_child set a=0 where 1=0;
已更新0行。
| aaa@AAA.US.ORACLE.COM>@showlockedobj |
可見(jiàn),當更新子表時(shí),會(huì )鎖住父子兩個(gè)表,即使實(shí)際上沒(méi)有更新數據
12 當更新父表時(shí):
aaa@AAA.US.ORACLE.COM>update test set a=0 where 1=0;
已更新0行。
| aaa@AAA.US.ORACLE.COM>@showlockedobj |
13 當父子兩個(gè)表同時(shí)更新時(shí):
session 1:
aaa@AAA.US.ORACLE.COM>update test_child set a=0 where 1=0;
已更新0行。
Session 2
aaa@AAA.US.ORACLE.COM>update test set a=1 where 1=0;
session 2會(huì )被鎖住.
| aaa@AAA.US.ORACLE.COM>@showlockedobj |
可見(jiàn),會(huì )發(fā)生死鎖.是由于第二個(gè)session申請子表的share鎖時(shí)發(fā)生的.
14對外鍵建立索引
aaa@AAA.US.ORACLE.COM>create index idx_child on test_child(a);
索引已創(chuàng )建。
當父子兩個(gè)表同時(shí)更新時(shí):
session 1:
aaa@AAA.US.ORACLE.COM>update test_child set a=0 where 1=0;
已更新0行。
Session 2
aaa@AAA.US.ORACLE.COM>update test set a=1 where 1=0;
已更新0行。
可見(jiàn),不會(huì )發(fā)生死鎖.
| aaa@AAA.US.ORACLE.COM>@showlockedobj |
可以發(fā)現,session 1獲得TEST_CHILD行級排他意向表鎖,同時(shí)獲得TEST表的行級共享排他意向鎖;
session 2獲得TEST行級排他意向表鎖,同時(shí)獲得TEST_CHILD表的行級共享排他意向鎖;
與上個(gè)例子相比,區別在于前面的例子中,session 1 獲得TEST_CHILD和TEST行級排他意向表鎖.
也就是說(shuō),對外鍵建立索引,可以防止兩個(gè)表的死鎖.
15 總結
Oracle通過(guò)具有意向鎖的多粒度封鎖機制進(jìn)行并發(fā)控制,保證數據的一致性。其DML鎖(數據鎖)分為兩個(gè)層次(粒度):即表級和行級。通常 的DML操作在表級獲得的只是意向鎖(RS或RX),其真正的封鎖粒度還是在行級;另外,在Oracle數據庫中,單純地讀數據(SELECT)并不加 鎖,這些都極大地提高了系統的并發(fā)程度。
在支持高并發(fā)度的同時(shí),Oracle利用意向鎖及數據行上加鎖標志位等設計技巧,減小了Oracle維護行級鎖的開(kāi)銷(xiāo),使其在數據庫并發(fā)控制方面有著(zhù)明顯的優(yōu)勢。
聯(lián)系客服