TransactionAbortedException - 你能安全地重新运行吗?

时间:2016-10-21 05:45:24

标签: c# sql-server

我正在以下列方式使用TransactionScope

using (var scope = new TransactionScope())
{
    using (var conn = SQLHelpers.GetSQLConnection())
    {  
          //commands here
    }
    scope.Complete();
}

有时我在调用TransactionAbortedException时收到scope.Complete(),因为事务已经回滚,我使用了探查器来确定问题是死锁。

  

异常事务(进程ID 59)在锁资源上与另一个进程发生死锁,并被选为死锁牺牲品。重新运行该交易。

我发现了死锁的原因但是它让我想知道为什么这个错误没有冒出TransactionAbortedException所以我确实可以为这个特定情况重新运行该事务。 内部异常不包含任何可以指示实际错误的信息。

检测TransactionAbortedException是重新运行交易的原因是否安全?

到目前为止,我已经看到了以下内部异常:

1)死锁
2)超时
3)'连接已关闭'
4)..其他?

在其中只有一种情况下,重新运行事务似乎是合适的,但是如果保证回滚,可以将其推广到所有情况。可以重新提出这个问题来询问“TransactionAbortedException”是否保证交易被回滚' ?

2 个答案:

答案 0 :(得分:3)

  

可以重新提出问题,问'做了吗?   TransactionAbortedException保证事务已滚动   回'

TransactionAbortedException的文档说:

  

尝试对事务执行操作时抛出此异常   已经回滚,例如,当您尝试时   在已超时的事务上调用Commit方法。   尝试提交时也会抛出此异常   交易和交易中止。

     

这是一个可恢复的错误。

我认为从这个描述中可以清楚地看出,如果你发现这个例外,由于某种原因你的交易没有成功完成。我对文档的理解是:“无论交易尝试做什么改变都没有提交给数据库”。

“这是一个可恢复的错误”,因此如果您的事务的性质使得重试它是有意义的,那么您应该在捕获此异常后重试它。

您可能希望在重试时引入一些逻辑,例如在重试之前等待一段时间。并且随着重试次数的增加而增加此等待时间。对所有重试次数或总重试次数进行限制,并在所有重试尝试都失败时,做一些合理/失败的事情。

答案 1 :(得分:0)

这个问题来了,但是我正在研究类似的问题。

您需要考虑几件事

  1. 这是嵌套事务的一部分。
  2. 可能会在将来。
  3. 是否正在运行任何异步事务。

如果重新运行内部事务,则外部范围事务的状态 可能已经受到威胁。相当容易测试。

  1. 创建嵌套事务,

  2. 在调试期间内部事务停止。

  3. 转到sql server并运行一些查询以锁定内部事务使用的表。

  4. 运行内部事务并等待死锁。

  5. 在收到TransactionAboted异常后,返回sql server并释放锁。

  6. 环回并重新运行内部事务。

  7. 检查内部交易状态。

  8. 在尝试提交外部事务之前检查外部事务的状态。