2010-10-18 197 views
2

我有一个转换,似乎没有回滚,并得到一个奇怪的错误。我正在使用与代码在同一服务器上的不同服务器上的SQL Server 2008和MSMQ连接的事务。下面是代码示例:交易不回滚

void MyMethod() 
    { 
     try 
     { 
      using (var outterTrans = new TransactionScope()) 
      { 
       try 
       { 
        InsertA(); 
        SendTransactionMsmqMsg(new BlahObject()); 
       } 
       catch (Exception e) 
       { 
        //Exception is getting written here. 
        using (new TransactionScope(TransactionScopeOption.Suppress))      
         HandleException(e); 

        throw; 
       } 

       InsertB(); 
       outterTrans.Complete(); 
      } 
     } 
     catch(Exception e) 
     { 
      //Exception is getting written here too. 
      HandleException(e); 
     } 
    } 

    public void InsertA() 
    { 
     //Inserts data. 
    } 


    public void InsertB() 
    { 
     //Inserts data. 
    } 

    void SendTransactionMsmqMsg(object obj) 
    { 
     //When calling Msmq.Send I get 'The PROMOTE TRANSACTION request failed because there is no local transaction active.' 
     Msmq.Send(CreateMessage(obj), MessageQueueTransactionType.Automatic); 
    } 

当这一切发生之前SendTransactionMsmqMsg不会被回滚。这种情况也非常罕见。这里是一些堆栈跟踪:

Type : System.Transactions.TransactionAbortedException, System.Transactions, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 
    Message : The transaction has aborted. 
    Source : System.Transactions 
    Help link : 
    Data : System.Collections.ListDictionaryInternal 
    TargetSite : Void CheckForFinishedTransaction(System.Transactions.InternalTransaction) 
    Stack Trace : at System.Transactions.TransactionStateAborted.CheckForFinishedTransaction(InternalTransaction tx) 
     at System.Transactions.EnlistableStates.Promote(InternalTransaction tx) 
     at System.Transactions.Transaction.Promote() 
     at System.Transactions.TransactionInterop.ConvertToOletxTransaction(Transaction transaction) 
     at System.Transactions.TransactionInterop.GetDtcTransaction(Transaction transaction) 
     at System.Messaging.MessageQueue.StaleSafeSendMessage(MQPROPS properties, IntPtr transaction) 
     at System.Messaging.MessageQueue.SendInternal(Object obj, MessageQueueTransaction internalTransaction, MessageQueueTransactionType transactionType) 
     at System.Messaging.MessageQueue.Send(Object obj, MessageQueueTransactionType transactionType) 
     ********Functions from my code here******** 

     Inner Exception 
     --------------- 
     Type : System.Transactions.TransactionPromotionException, System.Transactions, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 
     Message : Failure while attempting to promote transaction. 
     Source : System.Data 
     Help link : 
     Data : System.Collections.ListDictionaryInternal 
     TargetSite : Byte[] Promote() 
     Stack Trace : at System.Data.SqlClient.SqlDelegatedTransaction.Promote() 
      at System.Transactions.TransactionStatePSPEOperation.PSPEPromote(InternalTransaction tx) 
      at System.Transactions.TransactionStateDelegatedBase.EnterState(InternalTransaction tx) 

      Inner Exception 
      --------------- 
      Type : System.Data.SqlClient.SqlException, System.Data, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 
      Message : The PROMOTE TRANSACTION request failed because there is no local transaction active. 
      Source : .Net SqlClient Data Provider 
      Help link : 
      Errors : System.Data.SqlClient.SqlErrorCollection 
      Class : 16 
      LineNumber : 1 
      Number : 3965 
      Procedure : 
      Server : <machine> 
      State : 1 
      ErrorCode : -2146232060 
      Data : System.Collections.ListDictionaryInternal 
      TargetSite : Void OnError(System.Data.SqlClient.SqlException, Boolean) 
      Stack Trace : at System.Data.SqlClient.SqlConnection.OnError(SqlException exception, Boolean breakConnection) 
       at System.Data.SqlClient.SqlInternalConnection.OnError(SqlException exception, Boolean breakConnection) 
       at System.Data.SqlClient.TdsParser.ThrowExceptionAndWarning() 
       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.SqlInternalConnectionTds.ExecuteTransaction(TransactionRequest transactionRequest, String name, IsolationLevel iso, SqlInternalTransaction internalTransaction, Boolean isDelegateControlRequest) 
       at System.Data.SqlClient.SqlDelegatedTransaction.Promote() 

我不知道我在做什么错,什么是造成这个问题。我似乎无法生成这种相同的异常,并且我生成的每个异常都始终回滚。任何人都知道我可能会怎样产生这个错误?

感谢大家的帮助!

回答

1

DTC是否在涉及交易内部工作的所有服务器上运行?所有进程是否都有适当的访问权限?

这个职位有相同的错误消息给你: Membership.GetUser() within TransactionScope throws TransactionPromotionException

更新

凡被实例化的消息队列对象?我会尝试在事务范围内实例化它。

+0

是的,DTC正在所有服务器上运行。提交和回滚似乎正在工作,除了这个例外。这几乎就像是事务正在创建,但不知何故在MSMQ.Send调用之前被删除,这是错误的原因。由于交易已被移除,因此第一部分承诺是单一交易。或者TransactionScope吃了一个异常,所以它从来没有真正成为事务的一部分,所以第一部分承诺是因为它是一个单独的事务,当调用MSMQ.Send时,它检测到没有事务,这就是错误的原因。 – 2010-10-19 14:25:55

+0

看到我的更新另一件事尝试。有些事情导致数据库调用或MSMQ发送无法登记在事务处理事务中。 – 2010-10-19 14:38:28

+0

在构造函数对象中创建的线程已被多个线程使用。考虑一下,这可能是一个问题。现在我想到了,它发生在服务器上有负载时。 – 2010-10-19 14:50:12