一次分布式事務管理器(MSDTC)的事務處理異常的排錯


這兩天,因為一台MS SQL2005服務器的系統有些問題,重啟后不能正常登錄系統,采取了恢復上次正確配置的方式登錄。原來一直運行無問題的程序,在添加新記錄的時候,出現事務錯誤。而在編輯,刪除等均正常。

我的網絡環境是一台是Web服務器,一台是數據服務器,同一機房,相同網段,IP不一樣。

事務異常錯誤提示如下:

System.Transactions.TransactionManagerCommunicationException: 已禁用對分布式事務管理器(MSDTC)的網絡訪問。請使用組件服務管理工具啟用 DTC 以便在 MSDTC 安全配置中進行網絡訪問。 ---> System.Runtime.InteropServices.COMException (0x8004D024): 該事務管理器已經禁止了它對遠程/網絡事務的支持。 (異常來自 HRESULT:0x8004D024)
   在 System.Transactions.Oletx.IDtcProxyShimFactory.ReceiveTransaction(UInt32 propgationTokenSize, Byte[] propgationToken, IntPtr managedIdentifier, Guid& transactionIdentifier, OletxTransactionIsolationLevel& isolationLevel, ITransactionShim& transactionShim)
   在 System.Transactions.TransactionInterop.GetOletxTransactionFromTransmitterPropigationToken(Byte[] propagationToken)
   --- 內部異常堆棧跟蹤的結尾 ---
   在 System.Transactions.Oletx.OletxTransactionManager.ProxyException(COMException comException)
   在 System.Transactions.TransactionInterop.GetOletxTransactionFromTransmitterPropigationToken(Byte[] propagationToken)
   在 System.Transactions.TransactionStatePSPEOperation.PSPEPromote(InternalTransaction tx)
   在 System.Transactions.TransactionStateDelegatedBase.EnterState(InternalTransaction tx)
   在 System.Transactions.EnlistableStates.Promote(InternalTransaction tx)
   在 System.Transactions.Transaction.Promote()
   在 System.Transactions.TransactionInterop.ConvertToOletxTransaction(Transaction transaction)
   在 System.Transactions.TransactionInterop.GetExportCookie(Transaction transaction, Byte[] whereabouts)
   在 System.Data.SqlClient.SqlInternalConnection.GetTransactionCookie(Transaction transaction, Byte[] whereAbouts)
   在 System.Data.SqlClient.SqlInternalConnection.EnlistNonNull(Transaction tx)
   在 System.Data.SqlClient.SqlInternalConnection.Enlist(Transaction tx)
   在 System.Data.SqlClient.SqlInternalConnectionTds.Activate(Transaction transaction)
   在 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()
   在 System.Data.Linq.SqlClient.SqlConnectionManager.UseConnection(IConnectionUser user)
   在 System.Data.Linq.SqlClient.SqlProvider.get_IsSqlCe()
   在 System.Data.Linq.SqlClient.SqlProvider.InitializeProviderMode()
   在 System.Data.Linq.SqlClient.SqlProvider.System.Data.Linq.Provider.IProvider.Execute(Expression query)
   在 System.Data.Linq.Table`1.System.Linq.IQueryProvider.Execute[TResult](Expression expression)
   在 System.Linq.Queryable.FirstOrDefault[TSource](IQueryable`1 source, Expression`1 predicate)
   在 GCEVideoMonitor.BLL.SiteInfo.GetDeviceTypeKey(Int32 deviceTypeId, Int32 rtType)
   在 GCEVideoMonitor.Manage.Monitor.MonitorChannelManage.AddSubmit(Object sender, EventArgs e)

 

一開始,以為是MSDTC的問題,但我的MSDTC均有開啟,根據錯誤提示“已禁用對分布式事務管理器(MSDTC)的網絡訪問。請使用組件服務管理工具啟用 DTC 以便在 MSDTC 安全配置中進行網絡訪問”在網上搜索,配置與網上所說一致,嘗試了所有的方法,異常依然如此。后來也出現過下面的異常現象:

System.Transactions.TransactionManagerCommunicationException: 與基礎事務管理器的通信失敗。 ---> System.Runtime.InteropServices.COMException (0x80004005): 對 COM 組件的調用返回了錯誤 HRESULT E_FAIL。
   在 System.Transactions.Oletx.IDtcProxyShimFactory.ReceiveTransaction(UInt32 propgationTokenSize, Byte[] propgationToken, IntPtr managedIdentifier, Guid& transactionIdentifier, OletxTransactionIsolationLevel& isolationLevel, ITransactionShim& transactionShim)
   在 System.Transactions.TransactionInterop.GetOletxTransactionFromTransmitterPropigationToken(Byte[] propagationToken)
   --- 內部異常堆棧跟蹤的結尾 ---
   在 System.Transactions.TransactionInterop.GetOletxTransactionFromTransmitterPropigationToken(Byte[] propagationToken)
   在 System.Transactions.TransactionStatePSPEOperation.PSPEPromote(InternalTransaction tx)
   在 System.Transactions.TransactionStateDelegatedBase.EnterState(InternalTransaction tx)
   在 System.Transactions.EnlistableStates.Promote(InternalTransaction tx)
   在 System.Transactions.Transaction.Promote()
   在 System.Transactions.TransactionInterop.ConvertToOletxTransaction(Transaction transaction)
   在 System.Transactions.TransactionInterop.GetExportCookie(Transaction transaction, Byte[] whereabouts)
   在 System.Data.SqlClient.SqlInternalConnection.GetTransactionCookie(Transaction transaction, Byte[] whereAbouts)
   在 System.Data.SqlClient.SqlInternalConnection.EnlistNonNull(Transaction tx)
   在 System.Data.SqlClient.SqlInternalConnection.Enlist(Transaction tx)
   在 System.Data.SqlClient.SqlInternalConnectionTds.Activate(Transaction transaction)
   在 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()
   在 System.Data.Linq.SqlClient.SqlConnectionManager.UseConnection(IConnectionUser user)
   在 System.Data.Linq.SqlClient.SqlProvider.get_IsSqlCe()
   在 System.Data.Linq.SqlClient.SqlProvider.InitializeProviderMode()
   在 System.Data.Linq.SqlClient.SqlProvider.System.Data.Linq.Provider.IProvider.Execute(Expression query)
   在 System.Data.Linq.Table`1.System.Linq.IQueryProvider.Execute[TResult](Expression expression)
   在 System.Linq.Queryable.FirstOrDefault[TSource](IQueryable`1 source, Expression`1 predicate)
   在 GCEVideoMonitor.BLL.SiteInfo.GetDeviceTypeKey(Int32 deviceTypeId, Int32 rtType)
   在 GCEVideoMonitor.Manage.Monitor.MonitorChannelManage.AddSubmit(Object sender, EventArgs e)

仔細分析,並開啟代碼調試,發現“GCEVideoMonitor.BLL.SiteInfo.GetDeviceTypeKey(Int32 deviceTypeId, Int32 rtType)" 這個地方引起異常,把這個方法的代碼直接放在事務過程中使用,不調用該方法,這個地方的異常不再產生。

在添加帶有事務的新記錄,測試,出現下面的異常信息:

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.SqlClient.SqlInternalConnection.Enlist(Transaction tx)
   在 System.Data.SqlClient.SqlInternalConnectionTds.Activate(Transaction transaction)
   在 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()
   在 System.Data.Linq.SqlClient.SqlConnectionManager.UseConnection(IConnectionUser user)
   在 System.Data.Linq.SqlClient.SqlProvider.Execute(Expression query, QueryInfo queryInfo, IObjectReaderFactory factory, Object[] parentArgs, Object[] userArgs, ICompiledSubQuery[] subQueries, Object lastResult)
   在 System.Data.Linq.SqlClient.SqlProvider.ExecuteAll(Expression query, QueryInfo[] queryInfos, IObjectReaderFactory factory, Object[] userArguments, ICompiledSubQuery[] subQueries)
   在 System.Data.Linq.SqlClient.SqlProvider.System.Data.Linq.Provider.IProvider.Execute(Expression query)
   在 System.Data.Linq.ChangeDirector.StandardChangeDirector.DynamicInsert(TrackedObject item)
   在 System.Data.Linq.ChangeDirector.StandardChangeDirector.Insert(TrackedObject item)
   在 System.Data.Linq.ChangeProcessor.SubmitChanges(ConflictMode failureMode)
   在 System.Data.Linq.DataContext.SubmitChanges(ConflictMode failureMode)
   在 GCEVideoMonitor.DAL.GCEVideoMonitor3DataContext.SubmitChanges(ConflictMode failureMode) 位置 E:\正式項目VM2\GCE3.0\GCETeam\GCE3.0\GCEVideoMonitor\GCEVideoMonitor.DAL\Entities\GCEVideoMonitor3DataContext.Manager.cs:行號 56
   在 System.Data.Linq.DataContext.SubmitChanges()
   在 GCEVideoMonitor.DAL.GCEVideoMonitor3DataContext.SaveChanges() 位置 E:\正式項目VM2\GCE3.0\GCETeam\GCE3.0\GCEVideoMonitor\GCEVideoMonitor.DAL\Entities\GCEVideoMonitor3DataContext.Generated.cs:行號 999
   在 GCEVideoMonitor.Manage.Monitor.MonitorChannelManage.AddSubmit(Object sender, EventArgs e) 位置 E:\正式項目VM2\GCE3.0\GCETeam\GCE3.0\GCEVideoMonitor\GCEVideoMonitor.Manage\Monitor\MonitorChannelManage.aspx.cs:行號 161

該異常,網上有解析:

使用方式不當,主要有兩種吧:
1,先調用了事務,再去打開數據庫連接
2,在一個事務里面嵌套了另外一個事務

因此,在代碼里面修改如下:

 using (var ts = new System.Transactions.TransactionScope())
 {

  using (var dc = BLL.SiteInfo.CreateDBDataContext())
   {

      ....

   }

}               

變更為:

using (var dc = BLL.SiteInfo.CreateDBDataContext())
 {

 using (var ts = new System.Transactions.TransactionScope())
   {

      ....

   }

}       

成功添加了記錄,所有異常解決。

另外,我發覺我的電腦不能添加記錄,但在同事的電腦,他卻可以添加記錄,而不產生異常,是非常詭異的地方。

無語,隨筆以便后來者。

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM