在简化后看起来类似于下面的代码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秒,因此(没有一些奇怪的错误)它不能是mereTransaction / TransactionScope / DTC超时(它们都设置在30秒以北)。
Fwiw,这是conn1.Dispose()
之后和conn2.Open
之前的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()
答案 0 :(得分:1)
您的DTC超时似乎是一个问题,当您说明第二个连接并将事务提升为dtc事务时,它会超时。您可以在机器设置中更改超时。您更改了所有DTC事务的超时,因此在将其更改为较大值时可能会对性能产生影响。
machine.config中超时10分钟:
<configuration>
<system.transactions>
<machineSettings maxTimeout="00:10:00" />
</system.transactions>
</configuration>