0

我有一个喜欢的应用程序:

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 语句运行的原因是缺少回滚空间。有关更多信息,请参阅此问题

4

2 回答 2

1

您可能会遇到许多不同的问题。正如您所说,数据库挂起的主要原因是您的数据库遇到ORA-00257 Archiver error

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

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

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

于 2013-01-09T10:43:55.590 回答
1

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

如果表很大并且没有columnA='somevalue'查询将花费时间来验证您的条件的所有行。

您可以做的是在columnA. 在这种情况下,引擎将更快地知道具有该条件的行在哪里(索引搜索速度更快)。

如果您在并发系统中,另一种可能性是有人更新了您试图删除的行,但没有提交事务,因此该行被锁定。

于 2013-01-09T09:30:46.480 回答