自动提交打开时显式提交是否正常?

Dea*_*one 1 sql oracle

我一直在寻找,但是找不到这个.我正在使用Oracle并且有一个类似于的For循环:

BEGIN
  FOR YEARIDs IN (SELECT DISTINCT YEARID From MyTable)
  LOOP
    UPDATE (
              SELECT    ......
            )
    SET     MyFlag = 1;
    COMMIT;  -- Added
  END LOOP;
END;
Run Code Online (Sandbox Code Playgroud)

AutoCommit已打开,但似乎在整个FOR循环完成之前不会发生提交.因此,我在上面的代码中添加了Commit语句.这是否会导致任何意外结果,或者这是否违反了任何最佳做法?(即,当打开AutoCommit时,我不应该显式调用提交吗?)

谢谢,斯科特

编辑:糟糕...我使用Oracle 11g和Oracle SQL Developer作为客户端.

编辑:感谢您的回复,到目前为止.在运行查询的时间点,正在生成和调整数据.没有其他连接应该尝试访问数据.至于为什么我经常提交,在开发过程中,我针对数据的子集运行查询,并且查询运行得很好.该表保存了大约1400万条记录,我正在测试大约10万条记录.该查询相当复杂,并且针对该子集在大约5分钟内运行.当我针对整个表运行它时,查询运行超过14小时并且无法更新任何记录.我的理论是,保留那么多撤消信息可能会消耗开发服务器上的所有可用资源.如果我经常提交,则可以释放和重用该撤消信息.是的,它很慢.但是如果查询实际上已经完成,即使它需要整晚,那么它也可以移动到测试服务器.(并且可以在以后完成性能调整.)这个问题的截止日期早已过去.(在错过最后期限之后,我被带到了帮助中.而且我的专业领域不在于Oracle.)

Jus*_*ave 7

在循环内部提交通常是一个坏主意(因此允许任何工具自动提交).

在循环内部提交会使编写可重新启动的代码变得更加困难.如果在3次迭代后遇到错误会怎样?您现在已成功提交了2个UPDATE语句的结果.据推测,您需要确定哪些行已更新并编写代码以反转更新,或者您必须添加代码以避免尝试更新这两个成功yearid值的数据.这当然是可能的.但它涉及编写一堆代码来跟踪您的进度,并且通常会使您的代码更加复杂.

在循环内部提交会使代码变得更慢.承诺通常是相当昂贵的操作.因此,在循环中执行它通常是一个坏主意.如果你只有几十个循环迭代,这不是一个问题.但是如果你有数百或数千次迭代,你很容易就会花费大部分时间来提交.

在循环内部提交会大大增加您导致ORA-01555错误的风险.您的查询MyTable需要读取一致的数据视图.但是,如果您在循环内部提交,则告诉Oracle您的会话不再需要旧UNDO数据.如果Oracle碰巧清除UNDO了循环的后续迭代所需的数据,那么您将收到错误.然后,您将重新处理不可重新启动的代码,其中您成功完成了N次迭代,但您不知道哪些年份已处理或需要处理哪些年份.

在循环内部提交可能会产生数据一致性问题.例如,如果某些其他会话正在运行报告,那么这些报告很容易看到部分更新的数据,这通常意味着数据将不一致.如果3年的数据发生了变化,但其他年份没有变化,那么很难理解报告,人们(或流程)很容易做出错误的决策.

在循环内部进行提交也会降低代码的可重用性.如果您的代码包含提交(或者您在块中建立的保存点以外的回滚),则不能通过其他任何不希望提交其事务的代码来调用它.这导致人们尝试在没有事务控制的情况下重新实现逻辑,或者错误地违反事务完整性,这不可避免地导致他们构建引入数据一致性问题的应用程序.