Oracle的查詢重啟動

oracle_ace發表於2007-12-25

來演示一下寫一致性的查詢重啟動。

session 1:
------------
C:\Documents and Settings\Administrator>sqlplus /nolog

SQL*Plus: Release 9.2.0.8.0 - Production on 星期二 12月 25 21:19:28 2007

Copyright (c) 1982, 2002, Oracle Corporation.  All rights reserved.

SQL> conn hujinpei/passw0rd@icmnlsdb
已連線。
SQL> create table t ( x int , y int);

表已建立。

SQL> insert into t values (1 ,1);

已建立 1 行。

SQL> commit;

提交完成。

建立一個trigger來,觀察重啟動
SQL> create or replace trigger t_buffer
  2  before update on t for each row
  3  begin
  4     dbms_output.put_line('old.x = '||:old.x||', old.y = '||:old.y);
  5     dbms_output.put_line('new.x = '||:new.x||', new.y = ' || :new.y);
  6  end;
  7  /

觸發器已建立

SQL> set serveroutput on
SQL> update t set x=x+1;
old.x = 1, old.y = 1
new.x = 2, new.y = 1

已更新 1 行。

SQL> update t set x=x+1;
old.x = 2, old.y = 1
new.x = 3, new.y = 1

已更新 1 行。

SQL> update t set x=x+1;
old.x = 3, old.y = 1
new.x = 4, new.y = 1

已更新 1 行。

這個時候我們切換到session 2:
C:\Documents and Settings\Administrator>sqlplus /nolog

SQL*Plus: Release 9.2.0.8.0 - Production on 星期二 12月 25 21:19:54 2007

Copyright (c) 1982, 2002, Oracle Corporation.  All rights reserved.

SQL> conn hujinpei/passw0rd@icmnlsdb
已連線。
SQL> set serveroutput on
SQL> update t set x=x+10 where x>0;
old.x = 1, old.y = 1
new.x = 11, new.y = 1
old.x = 4, old.y = 1
new.x = 14, new.y = 1

已更新 1 行。

我們發現trigger被觸發了兩次

分析:
其實session 2的更新經歷了consistent read和current read兩個過程。由於session 1的transaction因為沒有提交而阻塞了session 2的更新,session 2開始執行update的時候就被session 1阻塞了,但是我們發現session 2會在where條件中尋找current read開始時資料庫已經提交的transaction,這個時候x的value是1,所以new.x=11。而當session 1提交後,oracle會重新啟動查詢更新。
而如果session 1沒有提交而是回滾了呢。那麼trigger就被觸發一次。

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

相關文章