Username: Password:

AUTONOMOUS TRANSACTION(自治事务)的介绍-数据库专栏,SQL Server
来源:作者: 发布时间:2007-12-26 01:59:23


 

 

在基于低版本的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

 

喜欢本文,那就收藏到:

    Del.icio.us Google书签 Digg Live Bookmark Technorati Furl Yahoo书签 Facebook 百度搜藏 新浪ViVi 365Key网摘 天极网摘 和讯网摘 博拉网 POCO网摘 添加到饭否 QQ书签 Digbuzz我挖网
相关评论  我也要评论
还没有关于此文章的相关评论!
  • 昵称: (为空则显示guest)
  • 评论分数: ★ ★ ★★★ ★★★★ ★★★★★
  • 评论内容:(不能超过250字,需审核后才会公布,请自觉遵守互联网相关政策法规。
  • 导航
    赞助商
    文章类别
    订阅