2

我遇到了一个偶尔会死锁的 Web 应用程序的问题

涉及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。

如果有人对我应该如何解决这个问题有任何想法,将不胜感激。

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

谢谢卡尔 R

4

5 回答 5

1

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

在修复死锁时,我总是喜欢做的第一件事就是调整所涉及的查询。如果您可以获得良好的性能改进,那么您将受益于更快的查询,以及大大减少发生死锁的机会。

于 2008-12-01T01:38:56.110 回答
1

——根据 jorgeburgos 的建议,然后……

如果这是一个僵局,那么,假设只有 2 名参赛者,一名应该是受害者,一名将完成。

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

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

于 2008-12-01T01:42:18.350 回答
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

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

于 2008-12-01T01:48:45.340 回答
1

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

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

否则,您可能必须分离并索引月份数据以提高更新效率

于 2008-12-01T01:51:36.537 回答
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;
    }
}
于 2010-04-16T18:28:01.857 回答