ORACLE中的自治事務


    這是一個非常實用的功能,特別用在記錄錯誤日志同時要回滾主事務的時候,我們在實際開發中就是這么用的,感覺還是很方便的。轉載一篇詳細的介紹,感謝原作者。

 

在基於低版本的ORACLE做一些項目的過程中,有時會遇到一些頭疼的問題.,比如想在執行當前一個由多個DML組成的transaction(事務)時,為每一步DML記錄一些信息到跟蹤表中,由於事務的原子性,這些跟蹤信息的提交將決定於主事務的commit或rollback. 這樣一來寫程序的難度就增大了, 程序員不得不把這些跟蹤信息記錄到類似數組的結構中,然后在主事務結束后把它們存入跟蹤表.哎,真是麻煩!

有沒有一個簡單的方法解決類似問題呢? 

ORACLE8iAUTONOMOUS TRANSACTION(自治事務,以下AT)是一個很好的回答。

AT 是由主事務(以下MT)調用但是獨立於它的事務。在AT被調用執行時,MT被掛起,在AT內部,一系列的DML可以被執行並且commit或rollback.

注意由於AT的獨立性,它的commit和rollback並不影響MT的執行效果。在AT執行結束后,主事務獲得控制權,又可以繼續執行了。

如何實現AT的定義呢?我們來看一下它的語法。其實非常簡單。

只需下列PL/SQL的聲明部分加上PRAGMAAUTONOMOUS_TRANSACTION就可以了。

可以加自治事務的有:

    1. 頂級的匿名PL/SQL塊

    2. Functions 或 Procedure(獨立聲明或聲明在package中都可)

    3. SQL Object Type的方法

  4. 觸發器。 

比如:  

在一個獨立的procedure中聲明AT

CREATE OR REPLACE PROCEDURE

  Log_error(error_msg IN VARCHAR2(100))

IS

  PRAGMA AUTONOMOUS_TRANSACTION;

BEGIN

  Insert into Error_log values ( sysdate,error_msg);

  COMMIT;

END;  

下面我們來看一個例子,(win2000 advanced server + oracle8.1.6 , connect as scott)

建立一個表:

create table msg (msg varchar2(120));

首先,用普通的事務寫個匿名PL/SQL塊: 

declare

  cnt number := -1;  --} Global variables

  procedure local is

  begin

     select count(*) into cnt from msg;

     dbms_output.put_line('local: # of rows is '||cnt);

      

     insert into msg values ('New Record');

     commit;

  end; 

  begin

     delete from msg ;

     commit;

     insert into msg values ('Row 1');

     local;

     select count(*) into cnt from msg;

     dbms_output.put_line('main: # of rows is '||cnt);

     rollback;

  

     local;

     insert into msg values ('Row 2');

     commit;

  

     local;

     select count(*) into cnt from msg;

     dbms_output.put_line('main: # of rows is '||cnt);

  end;

 

運行結果(注意打開serveroutput)

 

local: # of rows is 1  -> 子程序local中可以’看到’主匿名塊中的uncommitted記錄

main: # of rows is 2   -> 主匿名塊可以’看到’2條記錄(它們都是被local commit掉的)

local: # of rows is 2  -> 子程序local首先’看到’2條記錄,然后又commit了第三條記錄

local: # of rows is 4  -> 子程序local又’看到’了新增加的記錄(它們都是被local commit掉的),然后又commit了第五條記錄

main: # of rows is 5   -> 主匿名塊最后’看到’了所有的記錄. 

 

從這個例子中,我們看到COMMIT和ROLLBACK的位置無論是在主匿名塊中或者在子程序中,都會影響到整個當前事務. 

現在用AT改寫一下匿名塊中的procedure local:

...

  procedure local is

     pragma AUTONOMOUS_TRANSACTION;

  begin

...

 

重新運行(注意打開serveroutput)

local: # of rows is 0  -> 子程序local中無法可以’看到’主匿名塊中的uncommitted記錄 (因為它是獨立的)

main: # of rows is 2   -> 主匿名塊可以’看到’2條記錄,但只有一條是被commited.

local: # of rows is 1  -> 子程序local中可以’看到’它前一次commit的記錄,但是主匿名塊中的記錄已經被提前rollback了

local: # of rows is 3  -> 子程序local 中可以’看到’3條記錄包括主匿名塊commit的記錄

main: # of rows is 4   ->主匿名塊最后’看到’了所有的記錄.

 

很明顯,AT是獨立的,在它執行時,MT被暫停了. AT的COMMIT,ROLLBACK並不影響MT的執行.

 

運用AT時,有一些注意事項,簡單列舉如下:

1.    在匿名PL/SQL塊中,只有頂級的匿名PL/SQL塊可以被設為AT

2.    如果AT試圖訪問被MT控制的資源,可能有deadlock發生.

3.    Package 不能被聲明為AT,只有package所擁有的function和procedure 才能聲明為AT

4.    AT程序必須以commit 或rollback結尾,否則會產生Oracle錯誤ORA-06519: active autonomous transaction detected and rolled back

 

在程序開發時,如果充分運用AUTONOMOUS TRANSACTION的特性,一定能取得事倍功半的效果.

 

如果文章對你用,請支持萬事如意網址導航

再分享一下我老師大神的人工智能教程吧。零基礎!通俗易懂!風趣幽默!還帶黃段子!希望你也加入到我們人工智能的隊伍中來!https://blog.csdn.net/jiangjunshow


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM