首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> C語言 >> 關於C語言

C# 分散式交易實作指南:TransactionScope 與 MSDTC 設定全解析

     編輯:關於C語言

前言

當單一業務操作橫跨多個資料庫、多台伺服器,或需包含非資料庫資源(如訊息佇列、檔案系統)時,單一資料庫交易已無法滿足 ACID 需求。.NET Framework 提供 System.Transactions 命名空間,配合 Microsoft Distributed Transaction Coordinator (MSDTC),可輕鬆實現分散式交易。本文詳細說明核心用法、常見陷阱與環境設定。

核心場景:跨方法的原子性操作

// 業務邏輯:MethodA 成功才執行 MethodB,任一失敗全數回滾
int iGet = MethodA();
if (iGet > 0)
{
    MethodB(); // 可能拋出例外或回傳失敗
}

若 MethodA 寫入資料庫 A,MethodB 寫入資料庫 B(或同資料庫不同連線),需分散式交易保證一致性。

TransactionScope 使用範例

using System.Transactions;

public void ExecuteBusinessLogic()
{
    // 預設隔離級別:Serializable(最高,效能較低)
    // 可透過 TransactionOptions 調整 IsolationLevel
    using (TransactionScope scope = new TransactionScope())
    {
        try
        {
            int iGet = MethodA();
            if (iGet > 0)
            {
                MethodB();
            }
            
            // 關鍵:明確呼叫 Complete() 才會提交交易
            scope.Complete();
        }
        catch (Exception ex)
        {
            // 記錄日誌、拋出或處理
            // 若未呼叫 Complete(),Dispose 時自動回滾
            throw;
        }
    } // scope.Dispose() 隱式回滾(若未 Complete)
}

關鍵點解析

  1. 隱式升級:單一資料庫連線時使用輕量級 SqlConnection 區域交易;偵測到第二個連線或跨資源管理員時,自動升級為 MSDTC 管理的分散式交易。
  2. Complete() 必呼叫:忘記呼叫是最常見錯誤,導致交易無聲無息回滾。
  3. 例外處理:try-catch 內部例外若未吞沒,scope.Dispose() 會觸發回滾。若捕獲後不重拋,需手動決定是否 Complete()。
  4. 巢狀 Scope:預設 TransactionScopeOption.Required 會重用外層交易;可用 RequiresNew 強制建立獨立交易。

MSDTC 環境設定清單(多機器部署必讀)

分散式交易在開發機單機常能跑通,部署至多台伺服器頻繁失敗。請依序檢查:

1. 元件服務設定(兩台機器皆需設定)

  • 開啟 dcomcnfg → 元件服務 → 電腦 → 我的電腦 → 右鍵內容 → MSDTC 標籤 → 安全性設定
  • 勾選全部:網路 DTC 存取、允許遠端用戶端、允許遠端管理、允許輸入/輸出、啟用 TIP、無需驗證(測試環境;生產建議「相互驗證」)
  • 重新啟動 MSDTC 服務:net stop msdtc && net start msdtc

2. 網路連通與名稱解析

  • 雙向 Ping 通:ping <對方 NetBIOS 名稱> 與 ping <IP>
  • 確認 C:\Windows\System32\drivers\etc\hosts 含正確對應:
192.168.1.15  ServerB
192.168.1.10  ServerA

MSDTC 使用 RPC 動態連接埠,防火牆需開放 135 (RPC Endpoint Mapper) 及 動態連接埠範圍(預設 49152-65535),或透過 netsh int ipv4 set dynamicport tcp start=50000 num=1000 限制範圍並開放該範圍。

3. 驗證工具:DTCPing

  • 微軟官方工具 DTCPing 可模擬雙向 RPC 連線,快速診斷防火牆、DNS、權限問題。
  • 雙方皆執行 DTCPing.exe,一端作 Server,一端作 Client,觀察「RPC test successful」訊息。

進階主題

自訂交易選項

var options = new TransactionOptions
{
    IsolationLevel = IsolationLevel.ReadCommitted, // 降低隔離級別提升並發
    Timeout = TimeSpan.FromMinutes(2) // 超時時間
};
using (var scope = new TransactionScope(TransactionScopeOption.Required, options))
{
    // ...
}

非資料庫資源登記

實作 IEnlistmentNotification 介面,將自訂資源(如檔案操作、Web API 呼叫)納入交易管理:

public class FileTransaction : IEnlistmentNotification
{
    public void Prepare(PreparingEnlistment preparingEnlistment) { /* 備份檔案 */ }
    public void Commit(Enlistment enlistment) { /* 確認刪除備份 */ }
    public void Rollback(Enlistment enlistment) { /* 還原備份 */ }
    public void InDoubt(Enlistment enlistment) { /* 不確定狀態處理 */ }
}

// 使用時
Transaction.Current.EnlistVolatile(new FileTransaction(), EnlistmentOptions.None);

.NET Core / .NET 5+ 差異

  • System.Transactions 於 .NET Core 2.0+ 重新引入,但 僅支援 Windows(依賴 MSDTC)。
  • 跨平台分散式交易建議採用 Saga 模式、Eventual Consistency 或 DTM / CAP / MassTransit 等訊息總線框架實現補償交易。

常見錯誤與排查

錯誤現象可能原因解決方向
MSDTC on server 'X' is unavailableMSDTC 服務未啟動/防火牆阻擋/RPC 連接埠未開檢查服務、防火牆 135+動態埠、DTCPing 測試
The transaction has already been implicitly or explicitly committed or aborted巢狀 Scope 邏輯錯誤/連線池導致連線重用檢查 TransactionScopeOption 設定、確保連線在 Scope 內開啟
交易未回滾忘記呼叫 scope.Complete() / 吞沒例外代碼審查、加上 try-catch 重拋
效能極差預設 Serializable 隔離級別/長時間持有交易降級至 ReadCommitted、縮小 Scope 範圍、避免交易中呼叫外部 API

總結

TransactionScope 讓分散式交易編碼極簡單,但環境設定才是成敗關鍵。開發階段務必在測試環境驗證跨機器案例,上線前用 DTCPing 全流程驗證。現代雲原生架構下,若跨平台或微服務化,建議評估 Saga/事件驅動替代方案,降低對 MSDTC 的強依賴。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved