简体   繁体   English

死锁后重新提交事务

[英]Resubmit transaction after deadlock

I have a block of code wrapped in a transaction scope. 我有一个包含在事务范围内的代码块。 I'm using LINQ to communicate with the database. 我正在使用LINQ与数据库进行通信。 Once I capture a deadlock exception, how do I resubmit the transaction? 捕获死锁异常后,如何重新提交事务?

Basically, you just catch the deadlock exception and try the code again. 基本上,您只是捕获死锁异常并再次尝试代码。 We do something like this: 我们做这样的事情:

private static void ExecuteWithDeadlockRetry(int maxAttempts, bool useTransaction, Action action)
{
    int tryCount = 0;
    string errorMessage;

    // If use transaction is true and there is an existing ambient transaction (means we're in a transaction already)
    // then it will not do any good to attempt any retries, so set max retry limit to 1.
    if (useTransaction && Transaction.Current != null) { maxAttempts = 1; }

    do
    {
        try
        {
            // increment the try count...
            tryCount++;

            if (useTransaction)
            {
                // execute the action inside a transaction...
                using (TransactionScope transactionScope = new TransactionScope())
                {
                    action();
                    transactionScope.Complete();
                }
            }
            else
                action();

            // If here, execution was successful, so we can return...
            return;
        }
        catch (SqlException sqlException)
        {
            if (sqlException.Number == (int)SqlExceptionNumber.Deadlock && tryCount < maxAttempts)
            {
                // Log error here
            }
            else
            {
                throw;
            }
        }
    } while (tryCount <= maxAttempts);
}

And the call looks like this: 电话看起来像这样:

SqlDeadlockHelper.Execute(() =>
{
  // Code to execute here
}

Note that the Execute() method eventually calls ExecuteWithDeadlockRetry(). 请注意,Execute()方法最终调用ExecuteWithDeadlockRetry()。 There is a bit more to our solution than what you're asking, but this should give you some general direction. 我们的解决方案比您要求的要多一些,但这应该给您一些总体方向。

Think first and foremost why did the deadlock happen? 首先想一想为什么会发生僵局? Is it because a value you've read in you LINQ context and modified was changed by another transaction ? 是因为您在LINQ上下文中读取的值和已修改的值是否被另一个事务更改 The only reasonable action is to read again the values and decide if your changes make any sense with the new values . 唯一合理的操作是再次读取值并确定您的更改是否对新值有意义 Since this is ASP.NET, this implies showing the new values to the use, so you must return again the page to the user with a notice that a change occurred and it has to edit the data again. 由于这是ASP.NET,这意味着显示使用的新值,因此您必须再次将页面返回给用户,并注意发生了更改,并且必须再次编辑数据。

Automatic resubmit on deadlock is possible, but almost always is a bad idea. 在僵局自动重新提交可能的,但几乎总是是一个坏主意。 It will likely result in bad state in the database because your domain rules are broken as your retry overwrites changes that occurred after the value was read. 它可能会导致数据库中的状态错误,因为您的域规则被破坏,因为重试会覆盖读取值发生的更改。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM