Oracle 中的事务

Posted

技术标签:

【中文标题】Oracle 中的事务【英文标题】:Transactions in Oracle 【发布时间】:2016-10-10 14:59:36 【问题描述】:

我在 Oracle 数据库中作为第三方 API 的存储过程很少,我想在一个事务中链接这些 api 调用。我可以做吗? 据我了解that answer 我可以使用保存点。但是,如果这些 API 已经有提交语句,它是否有效? Oracle 是否会回滚嵌套提交?

另外,Oracle 如何处理保存点和并发? IE。如果我们有图表:

connection#1 (my api call)              connection#2 (3rd party api call)
savepoint sp1;
                                        savepoint sp2;
update t1 where id=1 set val=1;         update t1 where id=2 set val=2;
                                        commit; --done
call bad_stored_proc();
rollback to sp1;

这里会发生什么?回滚会仅影响行 (id=1,val=1),还是同时影响两行?

【问题讨论】:

您无法回滚已经提交的内容。所以在这种情况下,调用的顺序很重要,以及你想要回滚的究竟是什么。显然,您将无法回滚供应商 SP 的承诺工作。所以你必须专注于你自己的代码。你的代码是否依赖于厂商的 Sp 执行结果?它在调用顺序中的位置。它是第一个/最后一个还是在调用供应商的 SP 的中间?话虽如此,当您回滚时,您可以避免调用供应商的 sps,或者如果不可避免地在它们之后进行清理(应该非常小心,取决于那些 SP 所做的事情)。 如果他们(供应商的 SP)提交,这可能是一个“错误”或者供应商非常迫切地需要这样做,因此如果您选择这样做,您需要非常小心地清理它们这样做。 【参考方案1】:

Oracle 不会回滚嵌套提交。他们承诺。

您能做的最好的事情(也不是那么好)就是将第 3 方 API 包装在一个过程中,并用 PRAGMA AUTONOMOUS_TRANSACTION 标记该过程。这将限制第 3 方 API 只提交自己的工作。这意味着,如果您回滚,则将提交第 3 方事务工作,但不会提交您所做的任何其他工作。

这通常是一件非常糟糕的事情,因为它会使您的数据在绝大多数设计情况下逻辑上被破坏。我提到它是在不太可能的情况下面临的设计情况,您可以侥幸逃脱。

【讨论】:

【参考方案2】:

如果第三方过程在过程中调用了commit,那么在不修改过程本身的情况下,没有办法将它们全部作为一个事务运行。

Oracle 不支持嵌套提交或嵌套事务。提交意味着——您正在承诺将更改写入数据库并失去回滚更改的选项。

您可以使用会话参数来检查第三方过程是否包含任何提交语句。

alter session disable commit in procedure; 

使用此设置,任何尝试提交的过程都会抛出错误消息。*

感谢 Matthew McPeak 纠正了我对该参数作用的误解。

【讨论】:

以上是关于Oracle 中的事务的主要内容,如果未能解决你的问题,请参考以下文章

Oracle 中的事务

oracle中的事务

Oracle的自治事务

Webservice 中的 Oracle 事务回滚

事务的隔离级别以及oracle中的锁

Oracle事务