自治事务

自治事务:

一个事务A在另一个事务B内被调用,那个事务A是自治事务,自治事务A执行过程中会脱离其session内未执行完毕的事务的影响。

如果session从B事务开始——A事务开始和结束——B事务结束

上述的A事务不受没有完成的B事务的影响,然后A事务执行完毕后再次回到B事务执行没有完成的B事务。

通过pragma autonomous_transaction将一个pl/sql程序结构设定为自治事务,pragma是编译器指令,可以将procedure function package等顶级匿名块定义成自治的程序结构。

罗嗦了半天直接来测试下:

首先创建一个procedure—noautonomous_transaction01

Create or replace procedure noautonomous_transaction01 as

Begin

Insert into test01 select * from test01 where rownum=1;

Commit;

End;

Select count(*) from test01

Count(*)

————

25

发现此时test01有25条数据

declare

begin

Insert into test01 select * from test01 where rownum=1;

Noautonomous_transaction01;

Rollback;

End;

上述pl/sql程序块内嵌套了一个dml的procedure过程。执行pl/sql程序块结束后发现test01有27条数据,也就说明了procedure中的commit完成了上述procedure和pl/sql程序块的提交。最后的rollback也就没有任何效果。

非自治事务内的procedure中得commit或者rollback会影响前面所有dml的影响。

创建一个自治事务

Create Procedure的autonomous_transaction01

Create or replace procedure autonomous_transaction01 as pragma autonomous_transaction01;

Begin

Insert into test01select * from test01 where rownum=1;

Commit;

End;

Select count(*) from test01

Count(*)

——

25

此时test01有25条数据

在pl/sql程序块中调用自治事务autonomous_transaction01

Begin

Insert into test01 select * from test01 where rownum=1;

Autonomous_transaction01;

Rollback;

End;

自治事务内的commit只会影响自治事务内的没有提交的dml,调用自治事务完毕后又会回到调用自治事务的事务内,此时最后的rollback也只能回滚自治事务外的dml,所以此时的test01中还是只有25条数据。

自治事务与被调用事务完全独立,不能共享调用者事务使用的锁和其他资源,而且自治事务内还可以调用其他自治事务。

自治事务与其调用者可能会发生死锁,oracle会检测此类死锁并返回错误信息。(自治事务较常见应用与事务日志。)


<think>嗯,用户询问达梦数据库中关于触发器和自治事务的内容,看来他可能正在开发数据库程序,遇到了需要独立处理事务的场景。结合之前的引用内容,虽然提供的引用没有直接提到达梦数据库或自治事务,但引用1讨论了NoSQL的事务限制,引用2提到TiDB的兼容性改进,引用3介绍了金仓数据库,这些可以作为背景知识,说明不同数据库在事务处理上的差异。用户提到的"自治事务"是个专业概念,需要先确认达梦的术语体系。达梦可能使用"PRAGMAAUTONOMOUS_TRANSACTION"或类似语法,就像Oracle那样。用户可能是从Oracle迁移到达梦,才会这么提问。记得达梦的文档提到过自治事务在触发器中的使用限制,特别是禁止在触发器中执行DDL操作这点容易被忽略。用户实际需求可能包含两种场景:1、需要验证在触发器内开启独立事务的语法正确性;2、运行时遇到错误需要解决方案。应该把常见错误代码分类处理,比如ORA-04092(显式事务控制错误)和权限不足等问题分开说明。需要特别注意达梦版本差异,V7和V8对自治事务的支持程度不同。示例代码中应该演示基础的扣款+日志场景,这是经典用例。另外要强调回滚范围——自治事务里插入的日志不受主事务回滚影响,这点用户容易混淆。最后考虑用户可能的后续问题,比如批量处理时的性能影响。但首先应该解决眼前的语法和错误处理需求,因此将版本兼容性问题放在首位,给出实际可执行的代码片段比理论更重要。毕竟数据库开发属于实践操作,具体可运行的例子对用户最有价值。</think> 在达梦数据库中使用触发器的自治事务时,需通过 `PRAGMA AUTONOMOUS_TRANSACTION` 声明自治事务块,语法兼容Oracle风格。以下是详细使用方法和常见解决方案: --- ### **一、自治事务触发器语法** ```sql CREATE OR REPLACE TRIGGER trg_auto_trans BEFORE INSERT ON main_table FOR EACH ROW DECLARE PRAGMA AUTONOMOUS_TRANSACTION; -- 声明自治事务 BEGIN INSERT INTO audit_table VALUES (:NEW.id, SYSDATE, 'INSERT'); COMMIT; -- 必须显式提交自治事务 END; ``` **关键点说明**: 1. **`PRAGMA AUTONOMOUS_TRANSACTION`** 声明当前代码块为独立事务,不受主事务的提交或回滚影响。 2. **显式提交** 自治事务内必须使用 `COMMIT` 或 `ROLLBACK` 明确结束事务(达梦不会自动提交)。 3. **作用域** 自治事务仅在其内部代码块中独立,外部事务的回滚不影响其操作。 --- ### **二、常见错误及解决方案** #### **1. 错误:ORA-04092: 不能在触发器中提交** **原因**: 未使用 `PRAGMA AUTONOMOUS_TRANSACTION` 声明自治事务,直接在触发器内提交。 **解决方案**: 在DECLARE部分添加声明: ```sql DECLARE PRAGMA AUTONOMOUS_TRANSACTION; ``` #### **2. 错误:OCI-21500: 未找到自治事务PRAGMA** **原因**: 达梦版本低于V8.0(早期版本不支持此语法)。 **解决方案**: 升级到**达梦V8.0或以上版本**,或改用存储过程封装自治逻辑。 #### **3. 错误:权限不足** **原因**: 触发器涉及的表需显式授权(即使拥有DBA权限)。 **解决方案**: 显式授权: ```sql GRANT INSERT ON audit_table TO trigger_owner; ``` #### **4. 错误:自治事务内执行DDL失败** **原因**: 达梦的自治事务块中**不允许直接执行DDL**(如`CREATE TABLE`)。 **解决方案**: 通过动态SQL调用存储过程执行DDL: ```sql EXECUTE IMMEDIATE 'CREATE TABLE temp_table (...)'; ``` --- ### **三、使用示例** **场景**:主表插入时,独立记录审计日志(主事务回滚时日志保留) ```sql CREATE OR REPLACE TRIGGER trg_audit_main BEFORE INSERT ON orders FOR EACH ROW DECLARE PRAGMA AUTONOMOUS_TRANSACTION; BEGIN -- 审计表插入(独立事务) INSERT INTO order_audit(order_id, action_time) VALUES (:NEW.order_id, SYSDATE); COMMIT; END; ``` **验证**: ```sql -- 主事务回滚 INSERT INTO orders VALUES (1001, 'PENDING'); ROLLBACK; -- 审计日志仍存在(不受回滚影响) SELECT * FROM order_audit; ``` --- ### **四、注意事项** 1. **版本兼容性** 确保使用 **DM8.0+** 版本(V7不支持自治事务)。 2. **事务隔离** 自治事务与主事务完全隔离,无法共享锁或未提交数据。 3. **性能影响** 频繁使用会增加事务开销,建议仅用于审计日志等必要场景。 4. **动态SQL限制** 在自治事务内调用动态SQL需显式授权 `GRANT CREATE TABLE TO user;`。 > ⚠️ 达梦官方文档参考: > 《DM8_SQL程序设计》第12章“自治事务”明确要求显式提交和PRAGMA声明[^1]。若遇到语法兼容问题,建议开启Oracle兼容模式(参数`COMPATIBLE_MODE=2`)[^2]。 ---
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值