自治事务专为“主事务成败不可控但某操作必须落地”设计;核心判断标准是insert/update是否要求无论主事务commit或rollback都必须生效;典型场景包括错误日志、审计快照、异步通知标记、统计计数器更新。

自治事务不是“需要时就加”,而是专为「主事务成败不可控,但某件事必须落地」的场景设计。日志、审计、通知类操作用它最稳;读写主事务中间态、嵌套调用、匿名块里硬塞,基本等于白忙活。
什么时候必须用自治事务?
核心判断标准:你写的那条 INSERT 或 UPDATE,是否要求「不管主事务最后是 COMMIT 还是 ROLLBACK,它都得进表」。
- 错误日志记录:主过程抛异常、
ROLLBACK了,日志也得留下痕迹 - 操作审计快照:比如在触发器里记下某行被修改前的状态,不能因主事务回滚而消失
- 异步通知标记:发消息失败要记失败日志,这个日志不能随主流程一起丢
- 统计计数器更新:如「今日调用次数」这类全局指标,不依赖业务事务成败
PRAGMA AUTONOMOUS_TRANSACTION 放错位置的典型报错
它不是语句,是编译期指令,放错地方直接编译失败,而不是运行时报错。
- 放在
BEGIN后面 → 报PLS-00103或PLS-00702 - 塞在
IF分支或循环里 → 同样报PLS-00103 - 写在包规范(spec)里 → 编译不通过,因为 spec 不含实现逻辑
- 试图在 SQL*Plus 匿名块中用:
BEGIN ... PRAGMA AUTONOMOUS_TRANSACTION; ... END;→ 报PLS-00702,匿名块不支持
✅ 正确姿势:紧贴 IS 或 AS 后,声明区第一行,前面不能有任何变量、类型或游标声明。
自治事务里漏 COMMIT 或 ROLLBACK 的后果
不是“没生效”,而是 Oracle 主动回滚并抛出 ORA-06519 异常,你插的数据彻底消失。
- 正常路径末尾没写
COMMIT→ 出口无提交,必报错 -
EXCEPTION块里只RAISE,没ROLLBACK→ 异常一出,自治事务悬空,照样报ORA-06519 - 有多个出口(比如 IF/ELSIF/ELSE),每个分支都得覆盖提交或回滚
- 调用另一个自治过程?它自己也得管好自己的
COMMIT/ROLLBACK,不能指望外层兜底
容易被忽略的隔离性副作用
自治事务和主事务之间是真·互相看不见,这点在调试时最容易误判。
- 主事务刚
INSERT一行但没COMMIT,自治过程SELECT查不到——这是读已提交隔离,正常 - 自治过程自己
COMMIT了一条日志,主事务立刻能SELECT到——哪怕主事务最终ROLLBACK - 自治过程调用
SEQ.NEXTVAL,序列值永久推进,无法随主事务回滚 - 别在自治过程里查主事务临时表或基于未提交数据做逻辑判断,它根本不具备上下文
真正难的从来不是加那行 PRAGMA,而是想清楚:你写的那条语句,是否真的需要脱离主事务生命周期独立存在。一旦混淆,轻则日志丢失,重则序列错乱、死锁、数据不一致。











