我的交易完整性丧失与" TransactionInDoubtException"例外 [英] Integrity of my transaction is lost with "TransactionInDoubtException" exception
问题描述
我有试图插入条目的代码在一个MSDTC事务范围,如果有插入失败然后插入重试到特定阈值。
I have a code that tries to insert entries scoped in a MSDTC transaction and if there is insert failure then insertion is retried up to a specific threshold.
下面是代码:
while(!SaveToDb){
.......
Thread.Sleep(TimeSpan.FromMinutes(AppConfiguration.RetryInsertionDuringFailureIntervalInMin));
}
private bool SaveToDb()
{
try
{
......
using (var scope = new TransactionScope(TransactionScopeOption.Required, option))
{
Context.SaveEmail(_emailInfoList);
Context.SaveSyncState(syncState);
scope.Complete();
return true;
}
}
catch (Exception ex)
{
........
return false;
}
}
并有此异常遇到:
消息:本次交易是毋庸置疑的。堆栈跟踪:在
System.Transactions.TransactionStatePromotedIndoubt.PromotedTransactionOutcome(InternalTransaction
TX)的System.Transactions.CommittableTransaction.Commit()在
System.Transactions.TransactionScope.InternalDispose()为
System.Transactions.TransactionScope.Dispose()在
Presensoft.Exchange2010Puch.Core.PushJob.SaveEmailAndSyncState()
的InnerException信息:System.Data.SqlClient.SqlException(0x80131904):
超时已过期。
中的操作或服务器完成之前经过的超时周期没有响应。 --->
System.ComponentModel.Win32Exception(0x80004005的):等待操作
。在
System.Data.SqlClient.SqlInternalConnection.OnError超时(SQLEXCEPTION
例外,布尔breakConnection ,Action`1 wrapCloseInAction)在
System.Data.SqlClient.TdsParser.ThrowExceptionAndWarning(TdsParserStateObject
统计eObj,布尔callerHasConnectionLock,布尔asyncClose)在
System.Data.SqlClient.TdsParserStateObject.ReadSniError(在
System.Data.SqlClient.TdsParserStateObject.ReadSniSyncOverAsync()在System.Data.SqlClient.TdsParserStateObject.TryReadNetworkPacket结果
()结果$ b TdsParserStateObject
stateObj,UInt32的误差) $ b在System.Data.SqlClient.TdsParserStateObject.TryPrepareBuffer()在
System.Data.SqlClient.TdsParserStateObject.TryReadByte(字节&安培;价值)结果
在System.Data.SqlClient.TdsParser.TryRun (runBehavior runBehavior,
的SqlCommand cmdHandler,SqlDataReader的数据流,
BulkCopySimpleResultSet bulkCopyHandler,TdsParserStateObject
stateObj,布尔和放大器; dataReady)在
System.Data.SqlClient.TdsParser.Run(RunBehavior runBehavior,在
系统
的SqlCommand cmdHandler,SqlDataReader的数据流,
BulkCopySimpleResultSet bulkCopyHandler,TdsParserStateObject
stateObj) .Data.SqlClient.TdsParser.TdsExecuteTransactionManagerRequest(字节[]
缓冲区,TransactionManagerRequestType请求字符串transactionName,
TransactionManagerIsolationLevel ISOLEVEL,超时的Int32,
SqlInternalTransaction交易,TdsParserStateObject stateObj,
布尔isDelegateControlRequest )在
System.Data.SqlClient.SqlInternalConnectionTds.ExecuteTransactionYukon(TransactionRequest
transactionRequest,字符串transactionName,ISO的IsolationLevel在
系统
SqlInternalTransaction internalTransaction,布尔
isDelegateControlRequest)。 Data.SqlClient.SqlDelegatedTransaction.SinglePhaseCommit(SinglePhaseEnlistment
入伍)
Message : The transaction is in doubt. Stack Trace : at System.Transactions.TransactionStatePromotedIndoubt.PromotedTransactionOutcome(InternalTransaction tx) at System.Transactions.CommittableTransaction.Commit() at System.Transactions.TransactionScope.InternalDispose() at System.Transactions.TransactionScope.Dispose() at Presensoft.Exchange2010Puch.Core.PushJob.SaveEmailAndSyncState() InnerException : System.Data.SqlClient.SqlException (0x80131904): Timeout expired. The timeout period elapsed prior to completion of the operation or the server is not responding. ---> System.ComponentModel.Win32Exception (0x80004005): The wait operation timed out at System.Data.SqlClient.SqlInternalConnection.OnError(SqlException exception, Boolean breakConnection, Action`1 wrapCloseInAction) at System.Data.SqlClient.TdsParser.ThrowExceptionAndWarning(TdsParserStateObject stat eObj, Boolean callerHasConnectionLock, Boolean asyncClose) at System.Data.SqlClient.TdsParserStateObject.ReadSniError(TdsParserStateObject stateObj, UInt32 error) at System.Data.SqlClient.TdsParserStateObject.ReadSniSyncOverAsync()
at System.Data.SqlClient.TdsParserStateObject.TryReadNetworkPacket()
at System.Data.SqlClient.TdsParserStateObject.TryPrepareBuffer() at System.Data.SqlClient.TdsParserStateObject.TryReadByte(Byte& value)
at System.Data.SqlClient.TdsParser.TryRun(RunBehavior runBehavior, SqlCommand cmdHandler, SqlDataReader dataStream, BulkCopySimpleResultSet bulkCopyHandler, TdsParserStateObject stateObj, Boolean& dataReady) at System.Data.SqlClient.TdsParser.Run(RunBehavior runBehavior, SqlCommand cmdHandler, SqlDataReader dataStream, BulkCopySimpleResultSet bulkCopyHandler, TdsParserStateObject stateObj) at System.Data.SqlClient.TdsParser.TdsExecuteTransactionManagerRequest(Byte[] buffer, TransactionManagerRequestType request, String transactionName, TransactionManagerIsolationLevel isoLevel, Int32 timeout, SqlInternalTransaction transaction, TdsParserStateObject stateObj, Boolean isDelegateControlRequest) at System.Data.SqlClient.SqlInternalConnectionTds.ExecuteTransactionYukon(TransactionRequest transactionRequest, String transactionName, IsolationLevel iso, SqlInternalTransaction internalTransaction, Boolean isDelegateControlRequest) at System.Data.SqlClient.SqlDelegatedTransaction.SinglePhaseCommit(SinglePhaseEnlistment enlistment)
在此之后应用程序试图重新插入项,接下来是
System.Data.SqlClient.SqlException(0x80131904):PRIMARY
键约束违反 pk_email。
System.Data.SqlClient.SqlException (0x80131904): Violation of PRIMARY KEY constraint 'pk_email'.
在我看来,没有器transaction.commit()发射了成功(部分)已经提交发生在第一种情况下(MSDTC例外),这导致后者例外。
It looks to me that without transaction.commit() firing up successfully (partial) commit already took place in the first case(MSDTC exception) which led to the latter exception.
有什么办法,我可以找出是否提交发生时,有交易有疑问异常并回滚承诺,如果有任何。
Is there any way I can find out whether the commit has happened when there is "transaction is in doubt" exception and roll back the commit if there is any.
推荐答案
据的 MSDN :
According to MSDN:
在尝试对交易
是有疑问的行动,抛出此异常。事务是有疑问时不能确定
事务的状态。具体来说,
交易的最终结果,无论是提交或中止时,从来不知道这个
的交易。
当试图提交的
的交易和交易变得的不确定此异常也抛出。
This exception is also thrown when an attempt is made to commit the transaction and the transaction becomes InDoubt.
这是一个可恢复的错误。
This is a recoverable error.
编辑:
对于恢复:
你必须赶上 TransactionInDoubtException
&安培;写使用apt检查补偿逻辑。
For recovery:
You have to catch TransactionInDoubtException
& write compensate logic with apt checks.
using (var scope = new TransactionScope(TransactionScopeOption.Required, option))
{
try
{
Context.SaveEmail(_emailInfoList);
context.SaveSyncState(syncState);
scope.Complete();
return true;
}
catch (TransactionInDoubtException ex)
{
//check whether any one record from the batch has been partially committed . If committed then no need to reprocess this batch.
// transaction scope should be disposed first .
scope.Dispose();
if (IsReprocessingNeeded(syncState))
throw;
return true;
}
}
/// <returns></returns>
private bool IsReprocessingNeeded(SyncStateDataModal syncState)
{
while (true)
{
try
{
var id = _emailInfoList[0].ID;
bool isEmailsCommitted = Context.GetJournalEmail().FirstOrDefault(a => a.ID == id) != null;
if (!isEmailsCommitted)
return true;
if (context.EmailSynch(syncState.Id) == null)
{
context.SaveSyncState(syncState);
}
return false;
}
catch (Exception ex)
{
Thread.Sleep(TimeSpan.FromMinutes(AppConfiguration.RetryConnectionIntervalInMin));
}
}
}
源的什么是TransactionInDoubtException复苏路径
这篇关于我的交易完整性丧失与" TransactionInDoubtException"例外的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!