自治事务必须显式提交或回滚,否则抛ora-06519;仅可在存储过程、函数、包体、触发器中声明,不可嵌套;隔离性强,适合审计日志等独立持久化场景。

自治事务必须显式 COMMIT,否则报 ORA-06519
声明了 PRAGMA AUTONOMOUS_TRANSACTION 的过程,不是“自动提交”,而是“脱离主事务上下文后需自行终结”。只要没执行 COMMIT 或 ROLLBACK,退出时 Oracle 就会抛出 ORA-06519:active autonomous transaction detected and rolled back。
- 常见错误是只写
INSERT,忘了加COMMIT;尤其在EXCEPTION块里调用日志过程时,容易漏掉出口路径 - 如果逻辑有多个分支(比如正常结束、异常捕获、提前 RETURN),每个分支末尾都得确保有一次且仅一次
COMMIT或ROLLBACK - 不能靠外层事务“顺带提交”——自治事务的提交/回滚完全独立,外层
ROLLBACK不会影响它已落库的日志
日志表字段长度要防截断,别信 VARCHAR2(200)
SQLERRM 最长可达 4000 字节(不是字符),DBMS_UTILITY.format_error_backtrace 返回的堆栈文本也远超单行描述。字段拍脑袋设太小,等于主动丢关键信息。
-
MSG字段至少定义为VARCHAR2(4000);用CLOB反而可能触发自治事务下的隐式限制或性能问题 -
ERR_LINE字段也建议VARCHAR2(4000),因为format_error_backtrace返回的是多行调用链,含包名、行号、嵌套深度,不是单个数字 - 避免用
$$PLSQL_LINE替代format_error_backtrace——前者只返回当前语句行号,定位不到真正出错的嵌套位置
只能在存储过程/函数/触发器里声明,匿名块不行
PRAGMA AUTONOMOUS_TRANSACTION 是编译期指令,必须出现在可持久化子程序的声明区(即 IS 或 AS 后、BEGIN 前)。直接在 SQL*Plus 或 PL/SQL Developer 的匿名 BEGIN ... END; 块里加,会报 PLS-00702。
- 支持的位置:独立存储过程、函数、包体中的子程序、触发器体、对象类型方法
- 不支持:SQL*Plus 脚本里的 DECLARE 块、视图定义、内联函数表达式
- 临时测试?先建个临时过程,别硬塞进脚本里跑——否则连编译都过不去
日志过程参数设计要抓四类核心信息
一个能真正在生产排障中起作用的日志记录过程,至少得捕获业务上下文、错误码、堆栈和原始消息,且类型与 Oracle 内置函数输出严格对齐。
-
biz_code:传入业务单号、批次 ID 等,别用模糊值如'unknown',否则查日志时无法关联业务流水 -
errorline:必须用DBMS_UTILITY.format_error_backtrace,不是$$PLSQL_LINE -
errorcode:直接用SQLCODE,它是负数(如-1表示唯一约束冲突),别套ABS() -
msg:直接用SQLERRM,它已含ORA-xxxxx:前缀,重复拼接会导致格式混乱
最易被忽略的一点:自治事务里调用 SEQ.NEXTVAL 会真实推进序列值,且不可回滚——哪怕主事务最终失败,日志 ID 也不会复用。这本身不是 bug,但得心里有数。











