oracle事务必须显式控制,因默认关闭自动提交,dml后不commit/rollback则断连自动回滚;异常时须在exception中rollback兜底;批量操作宜用savepoint细粒度回滚;自治事务有访问限制且不可嵌套;commit位置决定事务原子性边界。

事务必须显式控制,不能依赖自动提交
Oracle默认关闭自动提交(AUTOCOMMIT=OFF),所有DML语句(INSERT/UPDATE/DELETE)都运行在未提交事务中。不写COMMIT或ROLLBACK,连接断开时会自动回滚——这点和MySQL/PostgreSQL完全不同,极易造成“明明执行了却查不到”的困惑。
- 开发时务必在每个可执行块末尾明确加
COMMIT或ROLLBACK,不能省略 - 存储过程中禁止依赖客户端工具(如SQL*Plus、SQL Developer)的自动提交设置,它们可能被误关
- 使用
DBMS_OUTPUT.PUT_LINE打印“执行成功”不等于已持久化,得看COMMIT是否真执行了
异常发生时,ROLLBACK必须放在EXCEPTION块里
PL/SQL遇到未捕获异常会立即终止,但不会自动回滚已执行的DML。若没在EXCEPTION中写ROLLBACK,就可能出现部分数据写入、部分失败的脏状态。
- 必须用
WHEN OTHERS THEN ROLLBACK兜底,不能只靠预定义异常分支 -
ROLLBACK后建议再抛出原错误(RAISE)或记录SQLERRM,否则上层调用方无法感知失败 - 避免在
EXCEPTION里只写DBMS_OUTPUT.PUT_LINE就结束——这等于静默丢弃异常
批量操作要用SAVEPOINT做细粒度回滚
单个事务包太多DML(比如循环插入1000条),一旦中途报错,ROLLBACK会把前面999条全撤掉。用SAVEPOINT可限定回滚范围。
- 在循环开始前建
SAVEPOINT sp_loop,每次迭代后检查SQL%ROWCOUNT - 出错时
ROLLBACK TO sp_loop,再继续下一轮,而不是中断整个过程 - 注意
SAVEPOINT名在同一个事务内不可重复,动态命名需拼接变量(如'sp_'||i)
自治事务(AUTONOMOUS_TRANSACTION)不是万能解药
想在主事务回滚时保留日志或审计记录?加PRAGMA AUTONOMOUS_TRANSACTION确实能隔离事务,但代价明显:
- 自治事务内不能访问主事务未提交的数据(
ORA-01445错误常见于此) - 嵌套自治事务不被支持,第二层
PRAGMA会编译失败 - 过度使用会导致事务边界混乱,调试时难以追踪数据实际落库时间点
INSERT,如果只在最后COMMIT,那它们就是原子的;如果每插一条就COMMIT一次,那就彻底失去事务保护。这个选择必须由业务语义驱动,而不是图代码“看着顺”。











