Oracle自治事务介绍

这是一个非常实用的功能,特别用在记录错误日志同时要回滚主事务的时候,我们在实际开发中就是这么用的,感觉还是很方便的。转载一篇详细的介绍,感谢原作者。


在基于低版本的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的特性,一定能取得事倍功半的效果.

 

参考博客:  http://wxy0327.itpub.net/post/16888/99854

<think>我们正在讨论Oracle自治事务(autonomous transaction)。根据用户的问题,用户想了解自治事务的概念和使用方法。根据引用[2],自治事务(AT)是由主事务(MT)调用但独立于它的事务。当AT被调用执行时,MT被挂起,AT内部可以执行一系列DML并提交或回滚,而不会影响MT的执行。AT结束后,MT继续执行。 使用场景:例如,在需要记录主事务的跟踪信息(如日志)而不受主事务提交或回滚影响时,可以使用自治事务。因为自治事务的提交是独立的,所以即使主事务回滚,自治事务中的操作(如日志记录)仍然会提交。 使用方法: 1. 在PL/SQL中,可以将一个过程或函数声明为自治事务。方法是在声明部分添加:PRAGMA AUTONOMOUS_TRANSACTION; 2. 在自治事务块中,必须执行一个提交(COMMIT)或回滚(ROLLBACK)操作,否则会报错(ORA-06519)。 示例: 创建一个自治事务过程,用于插入日志记录。 ```sql CREATE OR REPLACE PROCEDURE log_action (p_message VARCHAR2) IS PRAGMA AUTONOMOUS_TRANSACTION; -- 声明为自治事务 BEGIN INSERT INTO log_table (log_date, message) VALUES (SYSDATE, p_message); COMMIT; -- 必须显式提交或回滚 END; / ``` 在主事务中,可以调用这个自治事务过程: ```sql BEGIN -- 主事务操作 INSERT INTO employees (employee_id, name) VALUES (1001, 'John Doe'); -- 调用自治事务记录日志,即使主事务回滚,日志记录也不会被回滚 log_action('Inserted employee 1001'); -- 这里可以执行其他操作,然后决定提交或回滚主事务 -- 测试:回滚主事务 ROLLBACK; END; / ``` 在上面的例子中,主事务中的INSERT被回滚了,但是log_action过程插入的日志记录因为是在自治事务中提交的,所以会被保留。 注意事项: - 自治事务中不能使用主事务中未提交的数据(因为主事务被挂起且未提交,所以数据不可见)。 - 自治事务的提交只影响自己内部的操作,不影响主事务。 - 自治事务的回滚也只影响自己内部的操作。 自治事务Oracle 8i及更高版本中可用。 根据用户的问题,我们提供了概念和基本使用方法。接下来,生成相关问题。</think>### Oracle 自治事务详解 #### 概念说明 **Oracle 自治事务**(Autonomous Transaction,简称 AT)是一种独立于主事务的特殊事务类型[^2]。当调用自治事务时: 1. 主事务(Main Transaction, MT)会被暂时挂起 2. 自治事务独立执行 DML 操作(INSERT/UPDATE/DELETE) 3. 自治事务必须显式执行 COMMIT 或 ROLLBACK 4. 执行结束后,主事务恢复执行 $$ \text{主事务} \xrightarrow{\text{调用}} \boxed{\text{自治事务}} \xrightarrow{\text{返回}} \text{主事务继续} $$ 关键特性: - **事务隔离**:自治事务的提交/回滚不影响主事务状态 - **原子性独立**:自治事务内操作作为一个独立单元提交 - **可见性隔离**:自治事务看不到主事务未提交的修改 #### 使用方法 ##### 1. 声明自治事务(PL/SQL 示例) ```sql CREATE OR REPLACE PROCEDURE log_operation(p_msg VARCHAR2) IS PRAGMA AUTONOMOUS_TRANSACTION; -- 关键声明 BEGIN INSERT INTO audit_log(log_time, message) VALUES (SYSTIMESTAMP, p_msg); COMMIT; -- 必须显式提交 END; ``` ##### 2. 在主事务中调用 ```sql BEGIN -- 主事务操作 UPDATE accounts SET balance = balance - 100 WHERE id = 123; -- 调用自治事务(立即提交日志) log_operation('扣款100元'); -- 主事务可继续操作(日志已独立提交) INSERT INTO transactions(...) VALUES (...); COMMIT; -- 主事务提交(不影响已提交的日志) EXCEPTION WHEN OTHERS THEN ROLLBACK; -- 主事务回滚(日志记录仍保留) END; ``` #### 典型应用场景 1. **审计日志** 记录操作日志不受主事务结果影响[^2] 2. **错误日志** 在异常处理中持久保存错误信息 3. **实时状态更新** 更新进度状态(即使主事务失败) 4. **递归事务** 在触发器中执行额外数据操作 #### 注意事项 1. **必须显式提交/回滚** 否则报错 ORA-06519: active autonomous transaction 2. **资源限制** 每个自治事务消耗独立事务槽(TRANSACTIONS 参数) 3. **锁冲突风险** 自治事务可能被主事务锁阻塞 4. **版本支持** 需 Oracle 8i 或更高版本 ```mermaid graph LR A[主事务开始] --> B[执行DML1] B --> C{调用自治事务} C --> D[挂起主事务] D --> E[执行自治事务] E --> F[自治事务COMMIT] F --> G[恢复主事务] G --> H[执行DML2] H --> I[主事务COMMIT] ```
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值