的TransactionScope - 在底层提供对EnlistTransaction失败。

2019-09-01 09:11发布

我们的团队已经得到了表现为一个问题:

基础提供失败的EnlistTransaction; 无法访问已释放的object.Object名:“交易”。

这似乎一旦出现,我们开始使用的TransactionScope来处理我们的应用程序的交易。

栈跟踪的顶部部分被捕获为:

在System.Data.EntityClient.EntityConnection.EnlistTransaction(事务的事务)在System.Data.Objects.ObjectContext.EnsureConnection()在System.Data.Objects.ObjectContext.ExecuteStoreCommand(字符串的CommandText,对象[]参数)在Reconciliation.Models。 BillLines.BillLines.Reconciliation.Interfaces.IBillLineEntities.ExecuteStoreCommand在Reconciliation.Models.Legacy.EntityDbEnvironment.ExecuteOracleSql(字符串SQL)在EntityDbEnvironment.cs(字符串,对象[]):线41

同时在MSDTC日志更新,我已经使用提取的位置说明 :

pid=7060       ;tid=7908       ;time=04/29/2013-16:38:30.269   ;seq=136        ;eventid=TRANSACTION_BEGUN                        ;tx_guid=60f6390c-7570-488a-97a9-2c3912c4ca3e     ;"TM Identifier='(null)                                            '" ;"transaction has begun, description :'<NULL>'"
pid=7060       ;tid=7908       ;time=04/29/2013-16:38:30.269   ;seq=137        ;eventid=RM_ENLISTED_IN_TRANSACTION               ;tx_guid=60f6390c-7570-488a-97a9-2c3912c4ca3e     ;"TM Identifier='(null)                                            '" ;"resource manager #1002 enlisted as transaction enlistment #1. RM guid = 'defc4277-47a6-4cd9-b092-93a668e2097b'"
pid=7060       ;tid=7908       ;time=04/29/2013-16:38:31.658   ;seq=138        ;eventid=RECEIVED_ABORT_REQUEST_FROM_BEGINNER     ;tx_guid=60f6390c-7570-488a-97a9-2c3912c4ca3e     ;"TM Identifier='(null)                                            '" ;"received request to abort the transaction from beginner"
pid=7060       ;tid=7908       ;time=04/29/2013-16:38:31.658   ;seq=139        ;eventid=TRANSACTION_ABORTING                     ;tx_guid=60f6390c-7570-488a-97a9-2c3912c4ca3e     ;"TM Identifier='(null)                                            '" ;"transaction is aborting"
pid=7060       ;tid=7908       ;time=04/29/2013-16:38:31.658   ;seq=140        ;eventid=RM_ISSUED_ABORT                          ;tx_guid=60f6390c-7570-488a-97a9-2c3912c4ca3e     ;"TM Identifier='(null)                                            '" ;"abort request issued to resource manager #1002 for transaction enlistment #1"
pid=7060       ;tid=7908       ;time=04/29/2013-16:38:31.658   ;seq=141        ;eventid=RM_ACKNOWLEDGED_ABORT                    ;tx_guid=60f6390c-7570-488a-97a9-2c3912c4ca3e     ;"TM Identifier='(null)                                            '" ;"received acknowledgement of abort request from the resource manager #1002 for transaction enlistment #1"
pid=7060       ;tid=7908       ;time=04/29/2013-16:38:31.658   ;seq=142        ;eventid=TRANSACTION_ABORTED                      ;tx_guid=60f6390c-7570-488a-97a9-2c3912c4ca3e     ;"TM Identifier='(null)                                            '" ;"transaction has been aborted"

正如你所看到的RECEIVED_ABORT_REQUEST_FROM_BEGINNER一秒钟后RM_ENLISTED_IN_TRANSACTION被记录下来。

我们不明白的地方这中止请求从起源,或者它为什么被提出。 引起该问题的SQL是一个简单的SELECT,我们可以通过我们的数据库客户端没有问题执行。

该应用程序的工作的大部分时间,只是偶尔显示此问题。

我们使用的是Oracle 10.2.0.5.0实体框架。

UPDATE

继从@Astrotrain建议我成立了System.Transactions的记录。 产生的最后一项是字面上切断虽然中途:

....
<ApplicationData>
<TraceData>
<DataItem>
<TraceRecord xmlns="http://schemas.microsoft.com/2004/10/E2ETraceEvent/TraceRecord" Severity="Information">
<TraceIdentifier>http://msdn.microsoft.com/2004/06/System/Transactions/TransactionScopeCreated</TraceIdentifier>
<Description>TransactionScope Created</Description>
<AppDomain>BillLineGeneratorUI.exe</AppDomain>
<ExtendedData xmlns="http://schemas.microsoft.com/2004/03/Transactions/TransactionScopeCreatedTraceRecord">
<TraceSource>[Base]

正如你所看到的实际上除了防止日志整理。 我可以从这个中学到什么? 有任何想法吗?

Answer 1:

而不是使用MSDTC跟踪工具(我觉得可怕斯巴达),我可以推荐使用System.Transactions的跟踪源 - 只需在您的web.config中的以下内容:
如果您打开日志文件SvcTraceViewer.exe你会得到的步骤不错的视觉表现。

<configuration>
  <system.diagnostics>
   <trace autoflush="true" />
   <sources>
     <source name="System.Transactions" switchValue="Information">
       <listeners>
         <add name="tx"
              type="System.Diagnostics.XmlWriterTraceListener"
              initializeData="C:\MyApp-transactions-log.svclog" />
       </listeners>
     </source>
   </sources>
  </system.diagnostics>
</configuration>

不是一个解决方案本身,而是这可能给你什么不顺心的更多信息。



Answer 2:

至于你提到“应用程序工作的大部分时间,只是偶尔显示这个问题。” 这个我们可以得出这样的结论提供程序的分布式事务的支持,原因是其他一些间歇性故障或者在连接或处理。

  • 您使用嵌套事务范围,因为如果由于某种原因,内部范围被回滚(配置而不调用完成),将立即回滚外部事务导致错误。 使用TransactionScopeOption.Required(RequiresNew也会做,但RequiresNew有与之关联,因此最好使用所需的其他僵局有关的问题)来解决这个

  • 否则,它可能是因为一些其他的操作,而该交易活跃,在这种情况下使用的IsolationLevel = IsolationLevel.ReadCommitted来解决。



Answer 3:

我们有这个问题了。 解决这个问题的最好办法似乎打开一个新的数据库连接,只是做在交易中所需要的东西。 保持事务尽可能小总是好的。

 DatabaseContext db1 = new DatabaseContext();

 doSomeDatabaseActions(db1);

 TransactionOptions transOpts = new TransactionOptions();
 transOpts.IsolationLevel = System.Transactions.IsolationLevel.Serializable;

 using (TransactionScope scope = new TransactionScope(TransactionScopeOption.Required, transOpts))
 {
     using (DatabaseContext db2 = new DatabaseContext())
     {
        doDatabaseChecksWithLock(db2);
        doChanges(db2);
        db2.SaveChanges();
     }

     scope.Complete();
  }

我们有问题,没有引入第二个连接。 请注意,错误使用1个连接(DB1)如果交易被扩大(交易作出doSomeDatabaseActions一部分)也不见了。



Answer 4:

这也许应该是一个评论,但实在是太大了。 我希望它能帮助。

一个嵌套事务的最tipical错误的是:

using(TransactionScope outerScope = new TransactionScope())
{
    // Execute query 1

    using(TransactionScope innerScope = new TransactionScope())
    {
        try
        {
            // Execute query 2
        }
        catch (Exception)
        {
        }

        innerScope.Complete();
    }

    outerScope.Complete();
}

现在,如果查询2这是try / catch块内,rasies一个错误,你将捕获该异常在try / catch块,并处理它,但这里是一个supprise当您尝试将应用程序将引发第15行的的ObjectDisposedException完成交易。 这是因为DTC已捕捉到的异常,虽然你已经处理它,在那里已经部署了由.NET代码和交易的TransactionScope对象已回滚。 请注意,我所说的“对象”,这是因为无论是TransactionScope的对象已被布置,因为它们是同一个事务的一部分。



文章来源: TransactionScope - The underlying provider failed on EnlistTransaction. MSDTC being aborted