SQL Server大事务,然后偶尔命令超时

时间:2011-05-03 19:59:15

标签: sql-server transactions

我有一个导入大量数据的批处理。我这样做是通过读取一个大文本文件并解析,然后按数据指示执行插入,更新和删除。这些是作为存储过程执行的简单语句。一批存储过程调用被包装在事务中,以确保文件在继续之前已完全处理。批量导入每周进行一次。如果客户端落后,可能会连续出现几个大型事务。发生这种情况时,我偶尔会在第一个事件之后的事务中获得命令超时。我已将命令超时增加到120秒。到目前为止工作正常,但是,在慢速计算机上,它可能不会。我注意到超时通常发生在:

Update <table> set <columns> where <pk = some value>

我认为也许SQL仍然在后台更新索引。关于发生了什么的任何想法?

我意识到我可以使用像SqlBulkCopy这样的东西,但是,现在这不是一个选项。

谢谢, 斯科特

3 个答案:

答案 0 :(得分:3)

你的sproc是逐行还是基于set的INSERTS,UPDATES等?这个问题的答案将在几个段落中变得重要。

但首先,扩展超时的问题是n + 1问题,无论你做多长时间,都会出现这种情况仍然存在。因此,延长超时并不是一种永久性的睡眠,就像婴儿一样的解决方案。更好的方法是通过分解工作来消除超时的需要。

你要做的第一件事是消除包装交易。随着操作中的行数增加,维护锁所需的资源会爆炸,因此如果将这些操作分解为需要较小事务的较小步骤,这样的批处理操作通常会更快。

下一步,因为您不再拥有该包装事务,所以确保在作业失败的情况下可以安全地重新运行每个步骤,无论该过程何时失败。如果您想要使用,则称为“幂等”,如果您想使用普通英语,则称为“可重新运行”。

现在我们回到这个问题,你的sproc是逐行的,还是执行影响很多行的INSERTS,然后是UPDATES,等等。

CASE ROW-BY-ROW:最简单,但可能是最慢的。将文本文件放入“INBOX”表并添加“已处理”列,即Y / N.当您逐行进行时,执行INSERT,UPDATE或DELETE,然后将收件箱表中的行更新为Processed = Y.如果你在任何阶段拔出插件,sproc只会恢复查看未处理的行,直到没有剩下。这给你带来了与没有开销的伟大的大包装事务相同的影响。您可以连续运行几十个文件,服务器永远不会超时。

基于案例集:如果您正在进行基于集合的DML,那么您修改INSERT,以便它从INBOX表和INSERTS拉入目标表中,用于所有尚未存在的行。这使它可以重新运行。 DELETE语句不需要此检查,如果重新运行基于集合的DELETE并且它已经运行,它只是找不到要删除的内容。 UPDATE基本上与DELETE相同。

这是基于您对您的问题的陈述的一般建议。为了更具体,我需要了解更多有关该过程的信息。

答案 1 :(得分:1)

我会查看索引的碎片并在必要时重建它们。

此外,我会在SSMS中运行您的查询并启用包含实际执行计划,看看您是否有任何问题。

答案 2 :(得分:1)

您需要先调查导致超时的原因。与任何SQL Server性能调查一样,最佳方法是Waits and Queues方法。基本上,您需要查看wait_type中的wait_timewait_resourceUPDATE作为{{1}}的会话。这将显示阻止/减慢UPDATE的内容,根据此查找,您可以执行适当的操作/解决方案。如果我在黑暗中冒险,你在测试中遇到sys.dm_exec_requests事件。尽管如此,正确的解决方案是先测量并减少第二个:调查以确定超时的根本原因,然后才进行更改。