长期选择

时间:2018-04-09 10:21:14

标签: sql-server stored-procedures

我有一个夜间工作,它执行一个遍历表的存储过程并获取要插入另一个表的记录。

程序持续时间约为4-5分钟,在该表中,在具有~3M记录的表格上执行6次选择。

当此过程正在运行时,从另一个尝试更新同一个表的存储过程抛出异常:

  1.   

    事务(进程ID 166)在锁定资源上死锁   另一个进程并被选为死锁受害者。重新运行   事务。

  2.   

    执行超时已过期。超时时间过去之前   完成操作或服务器没有响应。 --->   System.ComponentModel.Win32Exception(0x80004005):等待操作   超时

  3. 我已阅读Why use a READ UNCOMMITTED isolation level? 个问题,但没有得出最符合我情景的结论,正如其中一条评论所述:

      

    "作者似乎暗示读取未提交/没有锁定将返回   上次提交的数据。我的理解是未经承认的   将返回最后设置的任何值,即使是未提交的   交易。如果是这样,结果将不会检索数据"一些   秒过时"。它会(或至少如果交易   写入您读取的数据后退了)检索数据   不存在或从未被提交过#34;

    考虑到我只关心夜间工作开始时行的状态(同时更新将在下一个计算中) 什么是最合适的方法?

1 个答案:

答案 0 :(得分:3)

  

事务(进程ID 166)在锁定资源上死锁   另一个进程并被选为死锁受害者。重新运行   事务。

这通常发生在您稍后通过放置共享锁来读取数据以更新它时,以下UPDATE语句无法获取必要的Update Locks,因为它们已被获取的共享锁阻止在导致僵局的不同会话中。

要解决此问题,您可以使用UPDLOCK选择记录,如下所示

SELECT * FROM [Your_Table] WITH (UPDLOCK) WHERE A=B

这将提前对记录进行必要的更新锁定,并将停止其他会话以获取记录上的任何锁定(共享/独占),并防止出现任何死锁。

死锁的另一个常见原因(Cycle Deadlock)是由于您在查询中放入的语句的顺序,最终每个查询在不同的事务中等待另一个查询。对于此类场景,您必须访问查询并修复排序问题。

  

执行超时已过期。超时时间过去之前   完成操作或服务器没有响应。 --->   System.ComponentModel.Win32Exception(0x80004005):等待操作   超时

这很清楚,您需要处理查询性能,并尽可能减少记录锁定。