偶尔死锁

时间:2008-12-01 01:31:35

标签: sql-server sql-server-2005 deadlock

我遇到了偶尔会陷入僵局的网络应用程序

涉及3个查询。 2正在尝试更新表

UPDATE AttendanceRoll
SET ErrorFlag = 0
WHERE ContractID = @ContractID
AND DATEPART(month,AttendanceDate) = DATEPART(month,@Month_Beginning)
AND DATEPART(year,AttendanceDate) = DATEPART(year,@Month_Beginning)

一个人正试图插入表格

INSERT INTO AttendanceRoll 
    (AttendanceDate, ContractID, PersonID, 
    StartTime, 
    EndTime, 
    Hours, AbsenceReason,
    UpdateCount, SplitShiftID, ModifiedBy, ModifiedDate)
SELECT   
    @P33,  @P34,  @P35,
    CONVERT(datetime,REPLACE( @P36, '.', ':')),
    CONVERT(datetime,REPLACE( @P37, '.', ':')),
    @P38,  @P39,  
    @P40, 1,  @P41, GETDATE()

死锁图显示了一种页面锁定和交换事件的循环排列,并且2个更新查询具有相同的服务器进程ID。

如果有人对如何解决这个问题有任何想法,那将非常感激。

如果有人需要,我可以发布死锁图。

由于 Carl R

5 个答案:

答案 0 :(得分:1)

更新查询是否需要花费大量时间才能执行(例如,超过秒)?如果是这样,请尝试优化查询(即通过将索引放在contractid列等)

在修复死锁时我总是喜欢做的第一件事就是调整所涉及的查询。如果您可以获得良好的性能提升,那么您将获得更快查询的好处,同时大大降低发生死锁的可能性。

答案 1 :(得分:1)

- 在jorgeburgos的建议之后,然后......

如果它陷入僵局,假设只有2名参赛者,一名应该是受害者,一名将完成。

您可以在数据层中构建死锁检测,并让它重试失败导致死锁的操作。

使用不同的表提示锁定机制来最小化所争议的资源范围。我不知道哪个适用于您正在使用的sql版本,但这里是来自MSDN。 http://msdn.microsoft.com/en-us/library/ms187373.aspx

答案 2 :(得分:1)

没有查看死锁图表和所涉及的工作负载,并且基于您所说的有关交换的内容,您可能会遇到涉及并行性的死锁。 http://msdn.microsoft.com/en-us/library/aa937571(SQL.80).aspx。您的死锁图形是否与上一篇文章中的一样?

您可以为查询禁用parralesim吗?有一个提示OPTION(MAXDOP 1)将在特定查询中禁用它。打开它,看看它是否有帮助。 http://msdn.microsoft.com/en-us/library/ms181714.aspx

优化索引也可以通过首先消除对parallesim的需求来缓解僵局。

答案 3 :(得分:1)

我猜你的更新正在进行表扫描,并最终将行锁升级为页锁到表锁,这会阻止插件完成

我认为有一个设置告诉它不要升级到行锁定之外,你可以尝试第一次

如果不这样做,您可能必须将月份数据分开并编制索引以使更新更有效

答案 4 :(得分:0)

我通常将我对SQL服务器的所有调用都包含在类似的内容中(确切地说这不会编译,但你会得到这个想法):

for (;;) {
    try {
        using (var t = BeginTransaction()) {
            DoTheCall();
            t.Commit();
            return;
        }
    }
    catch (SqlException ex) {
        if (ex.Number != 1205 && ex.Number != 601 && ex.Number != 605)
            throw;
    }
}