Oracle謹慎使用嵌套查詢做爲鎖機制條件

案例:Oracle 11g裏寫了一個存儲過程,內容爲執行update語句,更改表記錄狀態,目的是對錶記錄進行鎖定。應用服務器集羣調用同一個數據庫的這個存儲過程。最後發現,多個WebLogic實例都更新了同一條記錄。鎖機制失效。sql

進行代碼測試:數據庫

數據初始化準備服務器

create table tb_test_tab(
id number(10),
name varchar2(10),
statu varchar2(10)
);

truncate table tb_test_tab;
insert into tb_test_tab values (1001,'1','1');
insert into tb_test_tab values (1002,'2','1');
insert into tb_test_tab values (1003,'3','1');
insert into tb_test_tab values (1004,'4','1');
insert into tb_test_tab values (1005,'5','1');
insert into tb_test_tab values (1006,'6','1');
commit;

在plsql客戶端開2個sql窗口,第一個窗口執行如下語句,不進行提交事務。測試

update  tb_test_tab t set t.name='343333',t.statu='2' where t.statu='1' and t.id=1001;

第二個窗口同時執行如下語句,提交事務。spa

update  tb_test_tab t set t.name='343333',t.statu='3' where t.statu='1' and t.id=1001;
commit;

此時第二個語句的commit處於等待狀態,如今提交第一個窗口的事務,第二個事務也會當即提交。查看結果發現 t.id=1001記錄的 t.statu值爲2。說明表的鎖機制成功!code

如今換成嵌套語句做爲更新條件進行執行更新處理,看下鎖機制如何,操做步驟以下:事務

先初始化數據。it

truncate table tb_test_tab;
insert into tb_test_tab values (1001,'1','1');
insert into tb_test_tab values (1002,'2','1');
insert into tb_test_tab values (1003,'3','1');
insert into tb_test_tab values (1004,'4','1');
insert into tb_test_tab values (1005,'5','1');
insert into tb_test_tab values (1006,'6','1');
commit;

一樣在plsql客戶端開2個sql窗口,第一個窗口執行如下語句,不進行提交事務。語句含義就是將statu='1'的記錄升序後的前三條設置statu='2',name='22222'。table

update tb_test_tab t
   set t.name = '22222', t.statu = '2'
 where t.id in (select id
                  from (select r.id from tb_test_tab r where r.statu='1' order by r.id)
                 where rownum <= 3);

第二個窗口同時執行如下語句,提交事務。class

update tb_test_tab t
   set t.name = '33333', t.statu = '3'
 where t.id in (select id
                  from (select r.id from tb_test_tab r where r.statu='1' order by r.id)
                 where rownum <= 3);
commit;

此時第二個語句的commit處於等待狀態,如今提交第一個窗口的事務,第二個事務也會當即提交。查看結果發現id升序後的前三條記錄的 statu='3',name='33333'。 說明表的鎖機制存在異常,至少不是以前咱們想象的那樣的結果(以前想象的結果應該是 statu='2',name='22222'。 第二個窗口執行的語句更新記錄爲0條)!  這個也許就是Oracle內部鎖機制靈敏度不針對嵌套語句裏面的結果集。故須要謹慎使用嵌套語句做爲鎖機制的限制條件。

若是想上面嵌套語句不變,同時想讓鎖機制起到效果,能夠將嵌套語句裏面的限制條件在最外層再寫一遍便可。具體以下。第一個窗口改爲:

update tb_test_tab t
   set t.name = '22222', t.statu = '2'
 where t.id in (select id
                  from (select r.id from tb_test_tab r where r.statu='1' order by r.id)
                 where rownum <= 3)
    and t.statu='1';

第二個窗口改爲:

update tb_test_tab t
   set t.name = '33333', t.statu = '3'
 where t.id in (select id
                  from (select r.id from tb_test_tab r where r.statu='1' order by r.id)
                 where rownum <= 3)
    and t.statu='1';
commit;

相關文章
相關標籤/搜索