为什么一个SqlConnection获得封闭事务中间? [英] Why does a SqlConnection get closed mid-transaction?

查看:498
本文介绍了为什么一个SqlConnection获得封闭事务中间?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

在code,它简化看起来像以下, conn2.Open(),执行不到1秒的交易开始后(即没有超时问题)有时会抛出,声称(环境)的交易已经终止 - 换句话说,CONN2是没有问题的。

 使用(VAR TS1 =新的TransactionScope(...))
{
    使用(SqlConnection的CONN1 =新的SqlConnection(connStr1))
    {
        conn1.Open();
        变种CMD1 = conn1.CreateCommand();
        //使用CMD1 ..
    }

    使用(SqlConnection的CONN2 =新的SqlConnection(connStr2))
    {
        conn2.Open(); //这有时会抛出
        // ...
    }

    ts1.Complete();
}
 

出现此异常每次到目前为止,日志表明发生故障的事务,并收到了最后一笔交易之间至少有4.5漫长分钟没有任何交易,所以看起来可能是一个TCP连接可能已超时。

但是,如果如CONN1已经超时,它会已经扔在 conn1.Open()。相反,它抛出的 conn2.Open(),这说明 CONN1 已经关闭。

到底发生了什么,以 CONN1 ,为什么?为什么说它是打电话时只表示 conn2.Open()

在试图重现以上code中的问题,通过手动查杀底层TCP连接 CONN1 呼叫后 conn1.Dispose() ,我可以重现的出现几乎完全一样的堆栈跟踪conn2.Open()。只有 InvalidOperationException异常变成了 System.Data.SqlClient.SqlException ,一切是100%相同。但活动的CONN1和成功的 conn1.Dispose() conn2.Open()几乎没有时间结束之间,因此它不能成为一个超时。

这是对

  • 的WindowsServer 2008R2
  • 的.Net 3.5
  • 的SQLServer 2008R2

的异常和堆栈跟踪:

  System.Transactions.TransactionAbortedException:该交易已中止。
 ---> System.Transactions.TransactionPromotionException:失败而尝试以促进交易。
 ---> System.InvalidOperationException:请求的操作无法完成,因为连接已经断开。
   在System.Data.SqlClient.SqlInternalConnectionTds.ExecuteTransaction(TransactionRequest transactionRequest,字符串名称的IsolationLevel异,SqlInternalTransaction internalTransaction,布尔isDelegateControlRequest)
   在System.Data.SqlClient.SqlDelegatedTransaction.Promote()
   ---内部异常堆栈跟踪的结尾---
   在System.Data.SqlClient.SqlDelegatedTransaction.Promote()
   在System.Transactions.TransactionStatePSPEOperation.PSPEPromote(InternalTransaction TX)
   在System.Transactions.TransactionStateDelegatedBase.EnterState(InternalTransaction TX)
   ---内部异常堆栈跟踪的结尾---
   在System.Transactions.TransactionStateAborted.CheckForFinishedTransaction(InternalTransaction TX)
   在System.Transactions.Transaction.Promote()
   在System.Transactions.TransactionInterop.ConvertToOletxTransaction(交易成交)
   在System.Transactions.TransactionInterop.GetExportCookie(交易成交,字节[]下落)
   在System.Data.SqlClient.SqlInternalConnection.GetTransactionCookie(交易成交,字节[]下落)
   在System.Data.SqlClient.SqlInternalConnection.EnlistNonNull(交易TX)
   在System.Data.ProviderBase.DbConnectionInternal.ActivateConnection(交易成交)
   在System.Data.ProviderBase.DbConnectionPool.GetConnection(的DbConnection owningObject)
   在System.Data.ProviderBase.DbConnectionFactory.GetConnection(的DbConnection owningConnection)
   在System.Data.ProviderBase.DbConnectionClosed.OpenConnection(的DbConnection outerConnection,DbConnectionFactory connectionFactory的)
   在System.Data.SqlClient.SqlConnection.Open()
   在我的。code ...
 


修改(寻址提出的答案)

它可以是一个超时?正如我所提到的,错误发生时不到1秒到事务,所以(缺席一些奇怪的错误)它不可能是一个mereTransaction /的TransactionScope / DTC超时(全部设置为30秒北部)。

FWIW,这是经过DTC超时 conn1.Dispose()和前 conn2.Open 将有看上去像(在日语OS)。

  System.Transactions.TransactionException:ト​​ランザクションの状态に対して操作が有效ではありません。
 ---> System.TimeoutException:ト​​ランザクションがタイムアウトしました。
   ---内部例外スタックトレースの终わり---
   场所System.Transactions.TransactionState.EnlistPromotableSinglePhase(InternalTransaction TX,IPromotableSinglePhaseNotification promotableSinglePhaseNotification,交易原子事务)
   场所System.Transactions.Transaction.EnlistPromotableSinglePhase(IPromotableSinglePhaseNotification promotableSinglePhaseNotification)
   场所System.Data.SqlClient.SqlInternalConnection.EnlistNonNull(事务TX)
   场所System.Data.ProviderBase.DbConnectionInternal.ActivateConnection(交易成交)
   场所System.Data.ProviderBase.DbConnectionPool.GetConnection(的DbConnection owningObject)
   场所System.Data.ProviderBase.DbConnectionFactory.GetConnection(的DbConnection owningConnection)
   场所System.Data.ProviderBase.DbConnectionClosed.OpenConnection(的DbConnection outerConnection,DbConnectionFactory connectionFactory的)
   场所System.Data.SqlClient.SqlConnection.Open()
 

解决方案

这似乎是与你的DTC超时你,说明第二个连接的问题,这是超时的那一刻,促进交易DTC事务。您可以更改时间在机器设置。您更改超时所有DTC事务,所以你可以有一个性能的影响时,将其更改为一个较大的值。

一个10分钟超时machine.config中:

 <结构>
 < System.Transactions的>
   < machineSettings maxTimeout =00:10:00/>
 < /system.transactions>
< /结构>
 

In code that simplified looks something like the following, conn2.Open(), executed less than 1 second after the transaction was started (i.e. no timeout issue) sometimes throws, claiming the (ambient) transaction had already been aborted - in other words, conn2 is not the problem.

using (var ts1 = new TransactionScope(...))
{
    using (SqlConnection conn1 = new SqlConnection(connStr1))
    {
        conn1.Open();
        var cmd1 = conn1.CreateCommand();
        // use cmd1 .. 
    }

    using (SqlConnection conn2 = new SqlConnection(connStr2))
    {
        conn2.Open(); // THIS SOMETIMES THROWS
        // ...
    }

    ts1.Complete();
}

Every time this exception has occurred so far, the logs indicate that between the failing transaction and the last transaction before it there are at least 4.5 long minutes without any transaction, so it looks like perhaps a TCP connection could have timed out.

But if e.g. conn1 had timed out, it would already throw on conn1.Open(). Instead it throws on conn2.Open(), indicating that conn1 had been closed.

So what happened to conn1 and why? And why is it only indicated when calling conn2.Open()?

When trying to reproduce the problem with above code, by manually killing the TCP connection underlying conn1 after calling conn1.Dispose(), I can reproduce almost the exact same stack trace occurring on conn2.Open(). Only the InvalidOperationException turns into a System.Data.SqlClient.SqlException, everything else is 100% identical. But between the activity in conn1 and the successful conn1.Dispose() and conn2.Open() almost no time elapses, so it cannot be a timeout.

This is on

  • WindowsServer 2008R2
  • .Net 3.5
  • SQLServer 2008R2

The exception and stack trace:

System.Transactions.TransactionAbortedException: The transaction has aborted.
 ---> System.Transactions.TransactionPromotionException: Failure while attempting to promote transaction.
 ---> System.InvalidOperationException: The requested operation cannot be completed because the connection has been broken.
   at System.Data.SqlClient.SqlInternalConnectionTds.ExecuteTransaction(TransactionRequest transactionRequest, String name, IsolationLevel iso, SqlInternalTransaction internalTransaction, Boolean isDelegateControlRequest)
   at System.Data.SqlClient.SqlDelegatedTransaction.Promote()
   --- End of inner exception stack trace ---
   at System.Data.SqlClient.SqlDelegatedTransaction.Promote()
   at System.Transactions.TransactionStatePSPEOperation.PSPEPromote(InternalTransaction tx)
   at System.Transactions.TransactionStateDelegatedBase.EnterState(InternalTransaction tx)
   --- End of inner exception stack trace ---
   at System.Transactions.TransactionStateAborted.CheckForFinishedTransaction(InternalTransaction tx)
   at System.Transactions.Transaction.Promote()
   at System.Transactions.TransactionInterop.ConvertToOletxTransaction(Transaction transaction)
   at System.Transactions.TransactionInterop.GetExportCookie(Transaction transaction, Byte[] whereabouts)
   at System.Data.SqlClient.SqlInternalConnection.GetTransactionCookie(Transaction transaction, Byte[] whereAbouts)
   at System.Data.SqlClient.SqlInternalConnection.EnlistNonNull(Transaction tx)
   at System.Data.ProviderBase.DbConnectionInternal.ActivateConnection(Transaction transaction)
   at System.Data.ProviderBase.DbConnectionPool.GetConnection(DbConnection owningObject)
   at System.Data.ProviderBase.DbConnectionFactory.GetConnection(DbConnection owningConnection)
   at System.Data.ProviderBase.DbConnectionClosed.OpenConnection(DbConnection outerConnection, DbConnectionFactory connectionFactory)
   at System.Data.SqlClient.SqlConnection.Open()
   at My.Code...


Edit (addressing a proposed answer)

Can it be a timeout? As I mentioned, the error occurs less than 1 sec into the transaction, so (absent some weird bug) it cannot be a mereTransaction/TransactionScope/DTC timeout (which are all set north of 30 seconds).

Fwiw, this is what a DTC timeout after conn1.Dispose() and before conn2.Open would have looked like (on a Japanese language OS).

System.Transactions.TransactionException: トランザクションの状態に対して操作が有効ではありません。
 ---> System.TimeoutException: トランザクションがタイムアウトしました。
   --- 内部例外スタック トレースの終わり ---
   場所 System.Transactions.TransactionState.EnlistPromotableSinglePhase(InternalTransaction tx, IPromotableSinglePhaseNotification promotableSinglePhaseNotification, Transaction atomicTransaction)
   場所 System.Transactions.Transaction.EnlistPromotableSinglePhase(IPromotableSinglePhaseNotification promotableSinglePhaseNotification)
   場所 System.Data.SqlClient.SqlInternalConnection.EnlistNonNull(Transaction tx)
   場所 System.Data.ProviderBase.DbConnectionInternal.ActivateConnection(Transaction transaction)
   場所 System.Data.ProviderBase.DbConnectionPool.GetConnection(DbConnection owningObject)
   場所 System.Data.ProviderBase.DbConnectionFactory.GetConnection(DbConnection owningConnection)
   場所 System.Data.ProviderBase.DbConnectionClosed.OpenConnection(DbConnection outerConnection, DbConnectionFactory connectionFactory)
   場所 System.Data.SqlClient.SqlConnection.Open()

解决方案

It seems to be a problem with your DTC Timeout which is timed out at the moment you are stating the second connection and promote the transaction to a dtc transaction. You can change the time out in the machine settings. You change the timeout for all DTC transaction, so you can have a performance impact when changing it to a large value.

A 10 min timeout in machine.config:

<configuration>
 <system.transactions>
   <machineSettings maxTimeout="00:10:00" /> 
 </system.transactions>
</configuration> 

这篇关于为什么一个SqlConnection获得封闭事务中间?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆