zoukankan      html  css  js  c++  java
  • [转载]PRAGMA AUTONOMOUS_TRANSACTION

    数据库事务是一种单元操作,要么是全部操作都成功,要么全部失败。在Oracle中,一个事务是从执行第一个数据管理语言(DML)语句开始,直到执行一个COMMIT语句,提交保存这个事务,或者执行一个ROLLBACK语句,放弃此次操作结束。

    事务的“要么全部完成,要么什么都没完成”的本性会使将错误信息记入数据库表中变得很困难,因为当事务失败重新运行时,用来编写日志条目的INSERT语句还未完成。

    针对这种困境,Oracle提 供了一种便捷的方法,即自治事务。自治事务从当前事务开始,在其自身的语境中执行。它们能独立地被提交或重新运行,而不影响正在运行的事务。正因为这样, 它们成了编写错误日志表格的理想形式。在事务中检测到错误时,您可以在错误日志表格中插入一行并提交它,然后在不丢失这次插入的情况下回滚主事务。

    因为自治事务是与主事务相分离的,所以它不能检测到被修改过的行的当前状态。这就好像在主事务提交之前,它们一直处于单独的会话里,对自治事务来说,它们是不可用的。然而,反过来情况就不同了:主事务能够检测到已经执行过的自治事务的结果。

    要创建一个自治事务,您必须在匿名块的最高层或者存储过程、函数、数据包或触发的定义部分中,使用PL/SQL中的PRAGMA AUTONOMOUS_TRANSACTION语句。在这样的模块或过程中执行的SQL Server语句都是自治的。

    触发无法包含COMMIT语句,除非有PRAGMA AUTONOMOUS_TRANSACTION标记。但是,只有触发中的语句才能被提交,主事务则不行。

    exp:

    Create table Msg (Msg varchar(50)) ;
    自制事务:
    create or replace procedure AutoNomouse_Insert is
         PRAGMA AUTONOMOUS_TRANSACTION;
         begin
                 insert into Msg values('AutoNomouse Insert');
                commit;
        end;
    非自治事务:
    CREATE OR REPLACE Procedure NonAutoNomouse_Insert as
        begin
               insert into Msg Values('NonAutonomouse Insert');
               commit;
        end;

    SQL> begin
      2 
      3            insert into Msg Values('This Main Info');
      4 
      5            NonAutoNomouse_Insert;
      6 
      7            rollback;
      8 
      9  end
     10  ;
     11  /
     
    PL/SQL procedure successfully completed
     
    SQL> select * from msg;
     
    MSG
    --------------------------------------------------
    This Main Info
    NonAutonomouse Insert
    因为过程中有COMMIT;所以匿名块中得RULLBACK 是不起作用的; 由此得出:非自治事务中的COMMIT,ROLLBACK
    是会影响整个事务的。
    下面我们看一个另外一种情况:
    SQL> delete msg;
     
    2 rows deleted
     
    SQL>
     
    这里没有COMMIT;

    SQL> begin
      2 
      3            insert into Msg Values('This Main Info');
      4 
      5            rollback;  --这里加了ROLLBACK;
      6 
      7            NonAutoNomouse_Insert;
      8 
      9            rollback;
     10 
     11  end
     12  ;
     13  /
     
    PL/SQL procedure successfully completed
     
    SQL> select * from msg;
     
    MSG
    --------------------------------------------------
    This Main Info
    NonAutonomouse Insert
    NonAutonomouse Insert
     
    竟然没有ROLLBACK (DELETE * FROM SSG ;) 为什么了? 因为过程就是一个新的SESSION,所以前面的SESSION
    被正常EXIT,同时被自动提交; 所以我们会看到三行数据。
    SQL> commit;
     
    Commit complete
     
    SQL> select * from msg;
     
    MSG
    --------------------------------------------------
    This Main Info
    NonAutonomouse Insert
    NonAutonomouse Insert
     
    SQL> commit;
     
    Commit complete
     
    SQL> select * from msg;
     
    MSG
    --------------------------------------------------
    This Main Info
    NonAutonomouse Insert
    NonAutonomouse Insert
    因为这里一个新的SESSION 所以是没有意义的事务控制语句。
     
    SQL> delete msg;
     
    3 rows deleted
     
    SQL> commit;
     
    Commit complete
     
    SQL> select * from msg;
     
    MSG
    --------------------------------------------------
    可以看到这里是正常的提交;
     
    下面看一下自制事务:
    SQL> begin
      2 
      3            insert into Msg Values('This Main Info');
      4 
      5            AutoNomouse_Insert;
      6 
      7            rollback;
      8 
      9  end
     10 
     11  ;
     12  /
     
    PL/SQL procedure successfully completed
     
    SQL> select * from msg;
     
    MSG
    --------------------------------------------------
    AutoNomouse Insert
     
    我们看到是一行数据,显然第一条SQL INSERT 是被ROLLBACK,证明自制事务是一个独立于主程序的事务,
    他不会对主事务的控制产生影响。另外在分布式环境中我们经常会遇到 ORA-02064 ERROR ,就是因为主事务
    自己有事务控制语句,然而被调用的远程过程也有自己的事物控制语句,当然就会报错,我们将被调用的过程
    声明为自制事务那就OK了。
  • 相关阅读:
    SlickEdit 中 GDB 调试时SIG32 使得无法跟踪的问题 解决方法
    ln与mount
    ubuntu12.04 的 root 用户显示 中文 和 默认显示中文的方法
    ASP.NET MVC控制器作用
    ASP.NET管道模型
    第二章MVC框架如何截获请求
    第一章MVC与WebForms处理请求的区别
    asp.net运行原理一
    一个通配符引起的错误
    关于权限
  • 原文地址:https://www.cnblogs.com/sumsen/p/2647312.html
Copyright © 2011-2022 走看看