死锁后,为啥应用程序代码要等待再重试?

Posted

技术标签:

【中文标题】死锁后,为啥应用程序代码要等待再重试?【英文标题】:After a deadlock, why should application code wait before retrying?死锁后,为什么应用程序代码要等待再重试? 【发布时间】:2013-10-03 05:45:17 【问题描述】:

我想编写一些代码来检测死锁,如果发生死锁,请重试尝试的任何数据库操作,最多 n 次。我注意到人们经常在重试之间添加时间延迟。下面是一些 C# 代码来阐明我的意思:

void RetryIfDeadlocks(Action dbOperation, int maximumRetries)

    try
    
        dbOperation();
    
    catch (DeadlockException)
    
        var shouldRetry = maximumRetries > 0;

        if (shouldRetry)
        
            Task.Delay(millisecondsDelay: 300).Wait();
            RetryIfDeadlocks(dbOperation, maximumRetries - 1);
        
        else
            throw;
    

为什么这样的重试逻辑要在重试之间包含这样的时间延迟?

【问题讨论】:

Task.Delay(millisecondsDelay: 300).Wait() 那是一架竹子货机,还是说这样做比睡觉有好处? @Will,我不确定Task.Delay 是否优于Thread.Sleep。在我写这个问题的时候,我可能认为Task.Delay 没有人们与Thread.Sleep 关联的一些问题。还有什么是竹货机? en.wikipedia.org/wiki/Cargo_cult_programming Task.Delay 在使用 async/await 时更胜一筹,绝对... 【参考方案1】:

如果没有延迟,死锁重试可能会“猛击”网络/磁盘/数据库的活动,直到循环停止。最好在循环中放置一点延迟,让其他流量先通过(实际上这可能是解决死锁所必需的),然后再试一次。

【讨论】:

【参考方案2】:

没有必要等待才能取得进展。幸存的冲突事务很可能被授予了冲突事务争用的锁。

另一方面,另一个事务可能仍处于活动状态,并且可能正在做类似的事情。可能还会出现另一个僵局。稍作延迟后,其他交易可能是一个或正在做其他事情。

重试使第二次尝试成功的可能性更大。它不是正确性所必需的。

【讨论】:

以上是关于死锁后,为啥应用程序代码要等待再重试?的主要内容,如果未能解决你的问题,请参考以下文章

在循环中重试死锁,它们最终会解决吗?

AE CC 装不上,安装程序检测到计算机重新启动的过程可能暂停。建议退出安装程序,重新启动计算机,然后再重试。

如何在单个进程中模拟 SQL Server 中的死锁?

为啥在使用等待组和通道时会出现死锁?

在每个请求使用会话时如何让 NHibernate 重试死锁事务?

关于oracle数据库死锁,请大神进。为啥用java synchronized 关键字解决不了?怎么解决死锁问题?