【问题标题】:TransactionScope with uncommited first transaction fails on distributed transaction具有未提交的第一个事务的 TransactionScope 在分布式事务中失败
【发布时间】:2012-11-15 19:09:21
【问题描述】:

在尝试调试某些东西时,我发现代码有效地执行了以下操作:

  1. 创建 TransactionScope
  2. 创建一个事务(在本例中是一个 nHibernate tx,但不是很重要)
  3. 创建第二个事务(在本例中为标准 ADO.Net Tx)
  4. 提交第二个事务
  5. 在事务范围内调用 Complete()
  6. 处置事务范围。

现在 - 创建一个事务而不提交可能是个坏主意 - 尤其是当有(这就是错误修复)时。

但是,在测试时 - 我尝试了上述的各种组合(提交所有事务,一些事务,没有事务(即只有 TScope)提交第一个,但不是第二个,添加其他事务等)并且在所有的事情中我发现以下为真:

只有当我未能提交第一个事务并且事务范围变得分布式时,TScope 的 Dispose 才会失败:

System.InvalidOperationException : 该操作对于当前征募状态无效。

我现在很好奇,想知道为什么会这样?

【问题讨论】:

  • 我很困惑。 TransactionScope 的目的是拥有单个事务,可以是本地/轻量级事务,也可以是分布式事务。 TransactionScope 中的多个事务不是它的设计目的,并且违背了它的目的,恕我直言,这基本上是让 TransactionScope 在后台处理事务。您是指多个连接吗?
  • 好的.. 所以.. 两点进一步上述。上述情况似乎不太正确 - 在 TScope 内创建和未打开的任何 nHibernate 事务都会导致问题。为了澄清混淆:我们目前有一个没有事务范围的 nHibernate 堆栈。我们现在需要连接到另一个数据库。我看到的所有示例似乎都有: 1. 打开 TS 2. 打开 NH Tx 3. perorm NH work 4 Commit nh Tx 5 do other DB wrk 6 complete/dispose TS 你是说如果我们使用 TransacionScope,我们不应该使用nH 交易呢?此外 - 我们需要在 NH trans 中进行其他数据库工作。
  • 顺便说一句——TScope 似乎是我们想要的原因,因为我们并不总是需要做“其他数据库工作”——因此 TScope 会将它踢到分布式事务中。也许只使用 TScope(而不使用 NH 事务)是正确的解决方案 - 因为它无论如何都会创建一个事务?
  • 为了获得最佳结果,您应该始终使用 NH 事务。如果它发生在 TransactionScope 中,它将自动加入其中。如果没有 NH 事务,您可能会遇到问题,因为 NH 事务比 SQL 中的简单 BEGIN/ROLLBACK/COMMIT 具有更多的职责。

标签: c# nhibernate ado.net transactions transactionscope


【解决方案1】:

我怀疑您看到的问题是由以下之一解决的:https://nhibernate.jira.com/issues/?jql=project%20%3D%2010000%20AND%20labels%20%3D%20TransactionScope

我不完全确定会发生什么,但我看到过类似的行为,例如如果 NH 在环境事务中登记,并且事务稍后变为分布式,则调用 TransactionScope.Complete() 可能会挂起 20 秒然后失败。

即使您不使用 NH 事务,NH 也会尝试加入 TransactionScope。在这种情况下,NH 将在环境事务的 Prepare() 阶段刷新更改。它将在 db 连接上执行此操作,但这也已加入事务并将获得自己的 Prepare() 调用。不幸的是,我无法找出确切的问题,但我怀疑会发生什么,在某些情况下,数据库连接 Prepare() 将在 NHibernate 的 Prepare() 之前被调用。后者将尝试继续使用 db 连接,这似乎会导致某种死锁。

使用 NH 事务并在完成事务范围之前提交此事务将使 NH 在底层数据库连接进入准备阶段之前刷新其更改。

【讨论】:

  • 这绝对是相似的——只有当 tx 变为分布式时。我会确保我总是有一个 nH 交易。更多问题: 1. 将 ADO.Net 工作嵌套在 NH Begin/commit Transaction 中会有问题吗? 2、nH事务是否应该在commit后处理掉?我注意到(目前在添加 TScope 之前)我们尝试提交一个事务,然后处理它并开始一个新的 nH 事务。
  • 如果 ADO.Net 工作用于不同的数据库,它将使用单独的容器。 NH 不关心重叠的生命周期。如果工作是针对与 NH 连接的同一个数据库,您应该使用 NH 已经在管理的连接(和事务)。 2) 应始终处置一次性物品。
猜你喜欢
  • 2015-10-25
  • 2011-03-12
  • 1970-01-01
  • 1970-01-01
  • 2020-06-23
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-08-31
相关资源
最近更新 更多