数据库

本类阅读TOP10

·SQL语句导入导出大全
·SQL Server日期计算
·SQL语句导入导出大全
·SQL to Excel 的应用
·Oracle中password file的作用及说明
·MS SQLServer OLEDB分布式事务无法启动的一般解决方案
·sqlserver2000数据库置疑的解决方法
·一个比较实用的大数据量分页存储过程
·如何在正运行 SQL Server 7.0 的服务器之间传输登录和密码
·SQL中两台服务器间使用连接服务器

分类导航
VC语言Delphi
VB语言ASP
PerlJava
Script数据库
其他语言游戏开发
文件格式网站制作
软件工程.NET开发
AUTONOMOUS TRANSACTION(自治事务)的介绍

作者:未知 来源:月光软件站 加入时间:2005-2-28 月光软件站

 

 

在基于低版本的ORACLE做一些项目的过程中,有时会遇到一些头疼的问题.,比如想在执行当前一个由多个DML组成的transaction(事务)时,为每一步DML记录一些信息到跟踪表中,由于事务的原子性,这些跟踪信息的提交将决定于主事务的commit或rollback. 这样一来写程序的难度就增大了, 程序员不得不把这些跟踪信息记录到类似数组的结构中,然后在主事务结束后把它们存入跟踪表.哎,真是麻烦!

有没有一个简单的方法解决类似问题呢?

ORACLE8i的AUTONOMOUS TRANSACTION(自治事务,以下AT)是一个很好的回答。

AT 是由主事务(以下MT)调用但是独立于它的事务。在AT被调用执行时,MT被挂起,在AT内部,一系列的DML可以被执行并且commit或rollback.

注意由于AT的独立性,它的commit和rollback并不影响MT的执行效果。在AT执行结束后,主事务获得控制权,又可以继续执行了。

见图1:

 

1:

 

如何实现AT的定义呢?我们来看一下它的语法。其实非常简单。

只需下列PL/SQL的声明部分加上PRAGMA AUTONOMOUS_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的特性,一定能取得事倍功半的效果.

 

 

参考资料:

metalink.oracle.com

oracle8i manual

 




相关文章

相关软件