我想编写一些代码来检测死锁,如果发生死锁,请重试尝试的任何数据库操作,最多 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;
}
}
为什么此类重试逻辑应包括重试之间的时间延迟?
如果没有延迟,死锁重试可能会"猛击"网络/磁盘/数据库的活动,直到循环停止。最好在循环中放置一个小延迟,允许其他流量首先通过(实际上可能是解决死锁所必需的),然后再尝试。
等待不是取得进展的必要条件。幸存下来的冲突事务可能被授予了冲突事务所争用的锁。
另一方面,另一个事务可能仍然处于活动状态,并且可能正在做类似的事情。另一个僵局是可能的。经过一小段延迟后,其他事务可能是一个或现在正在做其他事情。
重试使第二次尝试成功的可能性更大。正确性不需要它。