在简化的代码中,类似于conn2.Open()
的代码,在事务启动后不到1秒执行(即,没有超时问题),有时会抛出该错误,声称(环境)事务已被中止-换句话说,conn2不是问题。
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();
}
到目前为止,每次发生此异常时,日志都会指出,在失败的事务和之前的最后一个事务之间,至少有4.5分钟的长时间没有任何事务,因此,看起来TCP连接可能已超时。
但是如果conn1已经超时,它已经抛出
conn1.Open()
了。而是抛出conn2.Open()
,表明conn1
已关闭。那么
conn1
发生了什么,为什么?为什么只在调用conn2.Open()
时才显示? 当尝试使用上述代码重现该问题时,通过在调用
conn1
之后手动终止conn1.Dispose()
下的TCP连接,我可以重现conn2.Open()
上发生的几乎完全相同的堆栈跟踪。只有InvalidOperationException
变成了System.Data.SqlClient.SqlException
,其他所有内容都是100%相同的。但是在conn1中的活动与成功的conn1.Dispose()
和conn2.Open()
之间几乎没有时间流逝,因此它不能是超时的。这是开
异常和堆栈跟踪:
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...
编辑(解决建议的答案)
可以超时吗?正如我所提到的,错误发生在交易发生的不到1秒之内,因此(没有一些奇怪的错误)不能仅仅是TransTransaction / TransactionScope / DTC超时(都设置在30秒以内)。
首先,这是
conn1.Dispose()
之后和conn2.Open
之前(在日语OS上)的DTC超时。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()
最佳答案
DTC超时似乎是一个问题,在您声明第二个连接并将事务升级为dtc事务时,该时间已超时。您可以在机器设置中更改超时。您可以更改所有DTC事务的超时,因此将其更改为较大值时可能会对性能产生影响。
machine.config中的10分钟超时:
<configuration>
<system.transactions>
<machineSettings maxTimeout="00:10:00" />
</system.transactions>
</configuration>
关于.net - 为什么SqlConnection在交易中间会关闭?,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/29004390/