TransactionAbortedException -你可以安全地重新运行

本文关键字:安全 重新运行 TransactionAbortedException | 更新日期: 2023-09-27 18:14:03

我以以下方式使用TransactionScope

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

有时我在调用scope.Complete()时得到TransactionAbortedException,因为事务已经回滚,并且我已经使用分析器来确定问题是死锁。

异常事务(进程ID 59)在锁资源上与另一个进程发生死锁,并被选为死锁受害者。重新运行事务。

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

检测TransactionAbortedException作为重新运行事务的原因是否安全?

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

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

?

似乎只适合在其中一种情况下重新运行事务,但是如果您保证回滚,则可以将其推广到所有情况。这个问题可以重新表述为"TransactionAbortedException是否保证事务被回滚?"

TransactionAbortedException -你可以安全地重新运行

这个问题可以重新表述为问"do a ?TransactionAbortedException保证事务被滚动回来的?

TransactionAbortedException的文档说:

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

这是一个可恢复的错误。

我认为这是非常清楚的,从这个描述,如果你捕捉到这个异常,你的事务没有成功完成由于某种原因。我对文档的理解是:"无论事务试图做什么更改,都没有提交给数据库"。

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

您可能希望在重试周围引入一些逻辑,例如在重试之前等待一段时间。并随着重试尝试次数的增加而增加等待时间。限制重试的总次数或总重试时间,并在所有重试尝试失败时做一些合理的/优雅的失败。

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

有几件事你需要考虑

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

如果内部事务重新运行,则外部事务的状态可能已经被泄露了。很容易测试。

  1. 创建嵌套事务,

  2. debug stop at inner transaction.

  3. 打开sql server,锁住内部事务使用的表

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

  5. 在收到transactionabted Exception后,返回sql server并释放锁

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

  7. 检查内部事务状态

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