• 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

  • 相关阅读:
    【转】小波与小波包、小波包分解与信号重构、小波包能量特征提取 暨 小波包分解后实现按频率大小分布重新排列(Matlab 程序详解)
    IPython:一种交互式计算和开发环境
    python防止字符串转义
    Could not find a version that satisfies the requirement numpy>=1.7.0 (from pan das==0.17.0) (from versions: ) No matching distribution found for numpy>=1.7.0 (from pandas==0.17.0)
    【转】出现“ValueError : numpy.ufunc has the wrong size, try recompiling" 解决方法
    【转】最简单的安装pip的方法
    小波变换教程(十七)
    小波变换补充知识
    小波变换教程(十六)
    C# 保护进程不被结束(源代码)防任务管理器结束进程
  • 原文地址:https://www.cnblogs.com/skiwdhwhssh/p/10295882.html
Copyright © 2020-2023  润新知