MS SQL Server 2005中 - 存储过程“自发打破”(MS SQL Server 200

2019-09-16 13:03发布

执行一个存储过程,当客户端报告的非常奇怪的行为一再发生。

他们有一条通往挥发性数据集的高速缓存转码。 一个存储过程写来重新处理需求,如果数据集:
1.自上次再处理的数据集已经改变
2. datset一直不变5分钟

(第二条件期间变化的时间停止大规模重复重新计算。)


这几个星期中,SP是服用1-2秒即可完成再处理工作的罚款,并在需要时只做到了。 然后...

  • 该SP突然“停止工作”(它只是不停地奔跑,再也没有回来)
  • 我们以一种微妙的方式改变了SP和一切又恢复了
  • 几天后,它停止工作再次
  • 然后有人说,“我们已经见过这个,只需重新编译的SP”
  • 在不改变代码中我们重新编译的SP,和它的工作
  • 几天后,它停止工作再次


这已经重复很多次。 该SP突然“停止工作”,从未返回和客户端超时。 (我们试图通过Management Studio中运行它,并在15分钟后取消了该查询。)

然而,每一个我们重新编译SP时,它突然再次工作。

我还没有试过在适当的EXEC statments RECOMPILE,但我不是特别想要做的任何方式。 它被调用的次数百小时,通常什么也不做(这只有几次重新处理数据的一天)。 如果可能的话我想避免重新编译的是一个相对复杂的SP的开销“,只是为了避免一些东西,‘不应该’发生...


  • 有谁之前经历过这个吗?
  • 有没有人对如何克服它有什么建议?


干杯,
民主党。


编辑:

该pseduo代码将如下所示:

  • 从TABLE_X读“一”
  • 从TABLE_X读“B”
  • 如果(A <B)的返回
  • BEGIN TRANSACTION
  • DELETE table_y
  • INSERT INTO table_y <3选择联合在一起>
  • UPDATE TABLE_X
  • COMMIT TRANSACTION

该选择是“不漂亮”,但是当在线执行的,他们在任何时间执行。 包括当SP拒绝完成。 而探查表明它是INSERT在该SP“摊位”

没有参数的SP,并显示sp_lock的阻止无关的过程。

Answer 1:

正如其他人所说,一些有关数据或源表的统计数据正在改变导致缓存的查询计划去陈旧。

WITH RECOMPILE可能会是最快的修复-使用SET STATISTICS TIME ON找出重新编译的成本实际上是贬失控之前。

如果这仍然不是一个可接受的解决方案,最好的选择可能是试图重构插入语句。

你不说,您是否使用UNIONUNION ALL在你的INSERT语句。 我见过INSERT INTOUNION产生一些奇怪的查询计划,特别是在2005年SQL的SP2之前的版本。

  • 删除和重建与目标表的拉吉的建议SELECT INTO是一条路可走。

  • 你也可以尝试选择这三个源的查询到自己的临时表,然后UNION在插入在一起的临时表。

  • 或者,你可以尝试的这些建议组合-把工会的结果与临时表SELECT INTO ,然后插入从到目标表。

我见过的在类似的这些方法解决性能问题; 测试将揭示这给你所拥有的数据的最好成绩。



Answer 2:

这是参数嗅探的足迹。 是的,第一步是尝试重新编译,虽然它并不总是工作,你希望它2005年的方式。

更新:我想尝试语句级重新编译的INSERT无论如何,因为这可能是一个问题的统计数据(噢,检查自动变速器统计更新是)。

如果这似乎并不适合参数嗅探,那么个实际的查询计划从当它正常工作,并从当它运行永远比(估计使用计划,如果你不能得到实际的,但实际是更好)。 您正在寻找,看是否计划改变与否。



Answer 3:

我完全参数嗅探诊断一致。 如果你有输入参数,这是不同的(或者即使他们没有改变)的SP - 一定有一个局部变量来掩盖他们在SP使用本地变量。

您也可以使用WITH RECOMPILE如果设定正在发生变化,但查询计划不再有任何好的。

在SQL Server 2008中,你可以使用OPTIMIZE FOR UNKNOWN功能。

另外,如果你的过程涉及填充一个表,然后使用该表中其他操作,我建议打破的过程分成不同的SP和独立美其名曰WITH RECOMPILE 。 我认为,在过程开始时所产生的计划,有时会非常差(这么差不完整),当你填充一个表,然后使用该表的结果来进行操作。 因为在最初的计划时,该表比初始插件后有很大不同。



Answer 4:

显然改变了存储过程(通过重新编译)的变化,导致了锁的情况。

尝试描述来记录你的SP的进步在这里或在这里 。



Answer 5:

我会同意与评论上面给出的答案,这听起来像一个未关闭的事务,特别是如果你仍然能够从查询分析器运行SELECT语句。

听起来很像有一个开放的事务挂起删除table_y和插入在这一点上是不可能发生的。

当你的SP锁定了,你可以执行INSERT INTO table_y?



Answer 6:

你有一个索引的维护工作?

是你的统计数据是最新的? 告诉一种方法是审查大的变化的估计和实际查询计划。



Answer 7:

正如其他人所说,这听起来很可能是未提交的事务。

我最好的猜测:

你要确保table_y可以完全和迅速删除。

如果有其他的存储过程或曾经持有此表上的交易代码外块,你可能会永远等待。 (他们可能因错误而从未关闭交易)

另注:尝试使用截断如果可能的话。 它使用较少的资源比任何一个删除where子句:

truncate table table_y

此外,一旦出错你自己的事务中发生,这将导致所有下列电话(每5分钟显然)“挂起”,除非你处理你的错误:

begin tran
begin try
 -- do normal stuff
end try
begin catch
 rollback
end catch
commit

该第一个错误是什么会给你实际的错误信息。 看到它在自己随后的测试挂只是一个辅助的作用。



Answer 8:

如果你正在做下列步骤操作:

DELETE table_y
INSERT INTO table_y <3 selects unioned together>

你可能想试试这个吧

DROP TABLE table_y
SELECT INTO table_y <3 selects unioned together>


文章来源: MS SQL Server 2005 - Stored Procedure “Spontaneously Breaks”