自治事务必须通过PRAGMA AUTONOMOUS_TRANSACTION声明触发,位置须紧邻IS/AS,不可在BEGIN后或函数体中间;用于绕过变异表限制、确保日志留存等解耦场景,且必须显式COMMIT或ROLLBACK。
触发自治事务必须加 PRAGMA AUTONOMOUS_TRANSACTION 声明
自治事务不是靠调用方式触发的,而是由编译器在解析子程序声明时识别出来的——没写这行声明,再怎么 commit 都属于主事务。它必须出现在子程序(procedure、function、包内子程序、匿名块)的声明部分,且必须紧挨着 is 或 as 之前或之后(oracle 和 opengauss 均要求位置严格)。
- 写在
BEGIN后面?无效,报错PLS-00103 - 写在函数体中间?不识别,仍走主事务逻辑
- 匿名块里也能用,但需完整声明结构:
DECLARE PRAGMA AUTONOMOUS_TRANSACTION; BEGIN ... COMMIT; END; - openGauss 25.1.32 要求
max_concurrent_autonomous_transactions > 0,否则直接报错ORA-00604: error occurred at recursive SQL level 1
为什么触发器里最常用自治事务
触发器天然受限于“变异表(mutating table)”和“不能在 DML 中提交”的双重约束。比如想在 BEFORE UPDATE 触发器里记录修改日志并抛异常中断更新,不加自治事务的话,日志插入会随主事务一起回滚,等于白记。
- 典型错误现象:
ORA-04091: table XXX is mutating, trigger/function may not see it或ORA-14552: cannot perform a DDL, commit or rollback inside a query or DML - 加了
PRAGMA AUTONOMOUS_TRANSACTION后,触发器内所有 DML +COMMIT都跑在独立 session 上,完全绕过变异表限制 - 注意:自治事务看不到触发器所在语句中未提交的行变更,比如你正在更新某行,触发器里查这张表,查不到这个“新值”
- 示例场景:审计型触发器、失败操作自动归档、发送告警前落库(即使主事务失败也要留痕)
COMMIT 和 ROLLBACK 在自治事务里是强制的
自治事务一旦启动,就必须显式结束——既不能靠主事务代为提交,也不能靠会话断开自动清理。忘了 COMMIT 或 ROLLBACK,会导致事务长期挂起,占用连接资源,严重时触发 max_concurrent_autonomous_transactions 限流而阻塞后续自治调用。
- 常见疏漏:异常分支里只写了
EXCEPTION WHEN OTHERS THEN NULL;,没做ROLLBACK - 正确写法要覆盖全部出口:
BEGIN ... COMMIT; EXCEPTION WHEN OTHERS THEN ROLLBACK; RAISE; - 函数里用自治事务要小心:函数被 SQL 调用时(如
SELECT my_log_func(...) FROM DUAL),若没COMMIT,会报ORA-14551: cannot perform a DML operation inside a query - openGauss 中,自治事务 session 断开后会自动
ROLLBACK,但 Oracle 不会,依赖显式控制
嵌套自治事务和变量可见性容易误判
自治事务可以嵌套调用(A 调 B,B 也声明了 PRAGMA AUTONOMOUS_TRANSACTION),但父子之间变量和数据变更并不共享,这点和普通子程序完全不同。
- 父过程改了包级变量
g_counter := g_counter + 1,自治子过程能读到新值,但自己改了不会反传回去(除非用IN OUT参数显式传递) -
ALTER SESSION SET NLS_DATE_FORMAT = 'YYYY-MM-DD'这类会话级设置,对所有自治事务都生效;但SET TRANSACTION ISOLATION LEVEL SERIALIZABLE只影响当前自治事务 - 游标行为取决于打开时机:在主事务里打开的游标,能看到主事务未提交的变更;在自治事务里打开的,一律看不到
- 性能提示:每次自治事务启动都会新建 session,高并发下易触发
max_concurrent_autonomous_transactions限制,别在循环里高频调用
PRAGMA AUTONOMOUS_TRANSACTION。

















