为什么Oracle在几次删除后陷入困境?

时间:2013-01-09 09:26:43

标签: oracle cycle

我有一个类似的应用程序:

delete from tableA where columnA='somevalue' and rownum<1000

在周期中:

 while(deletedRows>0) {
    begin tran
    deletedRows = session ... "delete from tableA where columnA='somevalue' 
    and rownum<1000"....
    commit tran

}

它运行几次(每次删除需要近20秒)并且在挂了很长时间之后 为什么?有可能解决吗? 感谢。


删除在循环而不是单个SQL语句中运行的原因是缺少回滚空间。有关详细信息,请参阅this question

2 个答案:

答案 0 :(得分:1)

每次查询从头开始扫描表。因此,它会扫描没有要删除的行的区域(columnA='somevalue')。他们越来越远离桌子的第一个街区。

如果表格很大且没有columnA='somevalue',则查询会花时间验证您所有情况的行。

您可以做的是在columnA上制作索引。在这种情况下,引擎将知道更快,具有该条件的行在哪里(搜索索引的指数时间更快)。

另一种可能性,如果你在一个concurent系统中,有人更新了你试图删除的行,但没有提交事务,所以该行被锁定。

答案 1 :(得分:1)

你可能遇到很多不同的问题。正如您所说数据库挂起的主要原因是您的数据库正在点击 ORA-00257存档错误

每次删除都会生成一个重做向量,然后将所有重做下载到存档日志中。当存档日志空间被耗尽时,会话会挂起并保持卡住,直到有人释放空间。 通常,您的DBA有一个每小时运行一次归档日志备份的作业(这可能是几个小时,或者每5分钟,具体取决于数据库工作负载等等),并且在备份完成后,所有会话都会正确进行。

根据数据库配置的不同,从客户端的角度来看,您可能看不到错误,只是描述了会话等待的行为,直到释放空间为止。

在设计方面,我同意其他用户认为循环中的DELETE并不是一个好主意。知道为什么要尝试执行此循环而不是单个DELETE语句可能会很有趣。