【问题标题】:TransactionAbortedException - can you safely re-run?TransactionAbortedException - 你能安全地重新运行吗?
【发布时间】:2016-10-21 05:45:23
【问题描述】:

我正在以下列方式使用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 的 InnerException 是超时了吗?
  • 不,唯一的InnerException 是:The COMMIT TRANSACTION request has no corresponding BEGIN TRANSACTION.,我得到这个是因为当事务被死锁回滚时,我调用了scope.Complete
  • 试试这个 if (Transaction.Current.TransactionInformation.Status == TransactionStatus.Committed) { scope.Complete(); }
  • @VladimirBaranov 没有特别询问死锁问题 - 我询问是否有任何 (db) 副作用需要重新运行(例如重新插入两次)当你遇到 TransactionAbortedException 时你刚刚运行的任何东西- 会稍微更新 q
  • 我认为创建一个Transaction对象并将其添加到TransactionScope中应该是一个好主意。 (交易范围(交易))。您可以在每个 sql 命令之后检查它,以了解何时或为什么会出现死锁。 (Transaction.TransactionInformation.Status)

标签: c# sql-server


【解决方案1】:

这个问题可以重新表述为“是否 TransactionAbortedException 保证事务被滚动 回来了?

TransactionAbortedException 的文档说:

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

这是一个可恢复的错误。

我认为从这个描述中可以很清楚地看出,如果你捕捉到这个异常,你的交易由于某种原因没有成功完成。我对文档的理解是:“事务尝试进行的任何更改都没有提交到数据库”。

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

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

【讨论】:

    【解决方案2】:

    这个问题迟到了,但我正在处理类似的问题。

    您需要考虑一些事项

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

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

    1. 创建嵌套事务,

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

    3. 去sql server运行一些查询来锁定内部事务使用的表。

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

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

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

    7. 检查内部交易状态。

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

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2021-08-04
      • 2020-11-23
      • 1970-01-01
      • 1970-01-01
      • 2011-01-25
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多