posts - 56, comments - 54, trackbacks - 0, articles - 4
             ::  ::  :: 聯(lián)系 :: 聚合  :: 管理

          PL/SQL支持嵌套事務(wù)

          Posted on 2006-01-27 16:20 Terry的Blog 閱讀(2258) 評論(1)  編輯  收藏 所屬分類: oracle

          使用場景:
          當(dāng)一個PL/SQL程序執(zhí)行出錯 需要輸出log信息到數(shù)據(jù)庫表中的時候 就會遇到這個難題.
          log的內(nèi)容要提交到表中 但是前面出錯的內(nèi)容卻不能提交.雖然我們可以在出錯時先Rollback 等log好了
          再commit.但是這樣畢竟比較麻煩.實際上PL/SQL本身支持嵌套事務(wù).
          看下面的小例子:
          CREATE OR REPLACE procedure Test1
          as
          PRAGMA AUTONOMOUS_TRANSACTION; -- 關(guān)鍵就是這句
          begin
          --set transaction read write;
          insert into aaa values(1,4,7);
          commit;
          end;
          /

          CREATE OR REPLACE procedure Test2
          as
          begin
          --set transaction read write;
          insert into aaa values(2,5,8);
          Test1;
          insert into aaa values(3,6,9);
          rollback;
          end;
          /
          當(dāng)execute Test2完了時在AAA表中插入了一行(1,4,7)。

          --------------------------------------------------------------------------------------------------------------------------
          理論知識:
          AUTONOMOUS TRANSACTION(自治事務(wù))的介紹:

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

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

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

          AT 是由主事務(wù)(以下MT)調(diào)用但是獨立于它的事務(wù)。在AT被調(diào)用執(zhí)行時,MT被掛起,在AT內(nèi)部,一系列的DML可以被執(zhí)行并且commit或rollback.

          注意由于AT的獨立性,它的commit和rollback并不影響MT的執(zhí)行效果。在AT執(zhí)行結(jié)束后,主事務(wù)獲得控制權(quán),又可以繼續(xù)執(zhí)行了。

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

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

          1.  頂級的匿名PL/SQL塊

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

          3.  SQL Object Type的方法

          4.  觸發(fā)器。

            比如:

           在一個獨立的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));

          首先,用普通的事務(wù)寫個匿名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;

          運行結(jié)果(注意打開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的位置無論是在主匿名塊中或者在子程序中,都會影響到整個當(dāng)前事務(wù).

          現(xiàn)在用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的記錄,但是主匿名塊中的記錄已經(jīng)被提前rollback了

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

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

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

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

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

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

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

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

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


          評論

          # re: PL/SQL支持嵌套事務(wù)  回復(fù)  更多評論   

          2013-03-20 00:59 by
          但是
          主站蜘蛛池模板: 象山县| 三亚市| 清涧县| 班玛县| 绿春县| 绥中县| 永年县| 阿合奇县| 正宁县| 崇信县| 张家界市| 英德市| 金寨县| 景洪市| 定陶县| 乌审旗| 崇左市| 凌海市| 攀枝花市| 奉新县| 永昌县| 扬州市| 亚东县| 前郭尔| 周口市| 锦屏县| 长治市| 石狮市| 九江市| 马山县| 隆德县| 大同市| 永嘉县| 闸北区| 定远县| 喀喇沁旗| 宜兰县| 武功县| 阳江市| 淮滨县| 泊头市|