跨雲端資料庫的分散式交易

適用於:Azure SQL DatabaseAzure SQL 受控執行個體

本文說明使用彈性資料庫交易,以讓您跨 Azure SQL Database 和 Azure SQL 受控執行個體的雲端資料庫執行分散式交易。 在本文中,「分散式交易」和「彈性資料庫交易」字詞視為同義字,並會交替使用。

注意

您也可以使用適用於 Azure SQL 受控執行個體的分散式交易協調器,以在混合環境中執行分散式交易。

概觀

針對 Azure SQL Database 與 Azure SQL 受控執行個體的彈性資料庫交易,可讓您跨多個資料庫執行交易。 彈性資料庫交易適用於使用 ADO .NET 的 .NET 應用程式,而且與以往熟悉使用 System.Transaction類別的程式設計經驗整合。 如要取得程式庫,請參閱 .NET Framework 4.6.1 (Web 安裝程式)。 此外,如果是受控執行個體,也可在 Transact-SQL 中使用分散式交易。

內部部署時,這種情節通常需要執行 Microsoft Distributed Transaction Coordinator (MSDTC)。 因為 MSDTC 不適用於 Azure SQL Database,所以協調分散式交易的功能已直接整合至 SQL Database 和 SQL 受控執行個體。 不過,針對 SQL 受控執行個體,您也可以使用分散式交易協調器以跨數個混合環境執行分散式交易,例如遍及受控執行個體、SQL Server、其他關聯式資料庫管理系統 (RDBMS)、自訂應用程式,以及任何可建立 Azure 網路連線的環境中所裝載的其他交易參與者。

應用程式可以連線至任何資料庫來啟動分散式交易,而其中一個資料庫或伺服器會明確地協調分散式交易,如下圖所示。

Distributed transactions with Azure SQL Database using elastic database transactions

常見的案例

彈性資料庫交易讓應用程式對數個不同的資料庫中儲存的資料,進行不可部分完成的變更。 SQL Database 和 SQL 受控執行個體都支援 C# 和 .NET 的用戶端開發體驗。 使用 Transact-SQL 的伺服器端體驗 (以預存程序或伺服器端指令碼撰寫的程式碼) 僅適用於 SQL 受控執行個體。

重要

不支援在 Azure SQL Database 和 Azure SQL 受控執行個體間執行彈性資料庫交易。 彈性資料庫交易只能跨 SQL Database 的一組資料庫,或跨受控執行個體的一組資料庫。

彈性資料庫交易針對下列案例:

  • Azure 的多資料庫應用程式:在此案例中,資料在 SQL Database 或 SQL 受控執行個體中的多個資料庫垂直分割,使得不同種類的資料位於不同的資料庫。 部分作業需要變更資料,而這些資料保存在兩個以上的資料庫中。 應用程式使用彈性資料庫交易來協調資料庫之間的變更,確保不可部分完成性。
  • Azure 的分區資料庫應用程式:在此案例中,資料層使用彈性資料庫用戶端程式庫或自行分區化,水平分割 SQL Database 或 SQL 受控執行個體中跨許多資料庫的資料。 一個顯著的使用案例是在分區化多租用戶應用程式中,當變更牽涉多個租用戶時,需要執行不可部分完成的變更。 例如,從一個租用戶轉移到另一個租用戶,而兩者位於不同的資料庫。 第二個案例是因應大型租用戶的容量需求而細部分區化,這通常表示一些不可部分完成的作業,需要在相同租用戶使用的多個資料庫延展。 第三種案例是以不可部分完成的更新來參考資料庫之間複寫的資料。 這類不可部分完成的交易式作業目前已可在多個資料庫間進行協調。 彈性資料庫交易使用兩階段交易認可,確保跨資料庫的交易不可部分完成性。 如果交易在單一交易中同時涉及的資料庫少於 100 個,便很適合使用這種方式。 這些限制不是強制規定,但超出這些限制時,彈性資料庫交易的效能和成功率必然下降。

安裝和移轉

彈性資料庫交易的功能是透過 .NET 程式庫 System.Data.dll 和 System.Transactions.dll 的更新提供。 DLL 確保必要時使用兩階段交易認可,以確保不可部分完成性。 若要使用彈性資料庫交易來開始開發應用程式,請安裝 .NET Framework 4.6.1 或更新版本。 在舊版 .NET Framework 上執行時,交易無法升級為分散式交易,將會引發例外狀況。

安裝後,即可透過連線至 SQL Database 和 SQL 受控執行個體的 System.Transactions,使用分散式交易 API。 如果您現有的 MSDTC 應用程式使用這些 API,在安裝 4.6.1 Framework 後,請重建 .NET 4.6 現有的應用程式。 如果專案以 .NET 4.6 為目標,便會自動使用新 Framework 版本中更新的 DLL 和分散式交易 API 呼叫,這時即可成功連線至 SQL Database 或 SQL 受控執行個體。

請記得,彈性資料庫交易不需要安裝 MSDTC。 而且,彈性資料庫交易是由服務直接管理。 這可大幅簡化雲端案例,因為 MSDTC 的部署不需使用 SQL Database 或 SQL 受控執行個體的分散式交易。 第 4 節更詳細地說明如何將彈性資料庫交易和必要的 .NET Framework 連同您的雲端應用程式一起部署到 Azure。

Azure 雲端服務的 .NET 安裝

Azure 會提供數個供應項目,以裝載 .NET 應用程式。 如需不同供應項目的比較,請參閱 Azure App Service、雲端服務與虛擬機器之比較。 如果供應項目的客體 OS 小於彈性交易所需的 .NET 4.6.1,則您必須將客體 OS 升級至 4.6.1。

對於 Azure App Service,目前不支援升級至客體 OS。 對於 Azure 虛擬機器,只要登入 VM,並執行最新的 .NET Framework 的安裝程式即可。 對於 Azure 雲端服務,您需要將新版 .NET 的安裝包含在您部署的啟動工作中。 在雲端服務角色上安裝 .NET中說明概念和步驟。

請注意,相較於 .NET 4.6 的安裝程式,.NET 4.6.1 的安裝程式在 Azure 雲端服務上進行啟動程序期間,可能需要更多的暫存儲存空間。 為了確保能夠順利安裝,您必須在 ServiceDefinition.csdef 檔案中,於啟動工作的 LocalResources 區段和環境設定中,增加 Azure 雲端服務的暫存儲存體,如以下範例所示:

<LocalResources>
...
    <LocalStorage name="TEMP" sizeInMB="5000" cleanOnRoleRecycle="false" />
    <LocalStorage name="TMP" sizeInMB="5000" cleanOnRoleRecycle="false" />
</LocalResources>
<Startup>
    <Task commandLine="install.cmd" executionContext="elevated" taskType="simple">
        <Environment>
    ...
            <Variable name="TEMP">
                <RoleInstanceValue xpath="/RoleEnvironment/CurrentInstance/LocalResources/LocalResource[@name='TEMP']/@path" />
            </Variable>
            <Variable name="TMP">
                <RoleInstanceValue xpath="/RoleEnvironment/CurrentInstance/LocalResources/LocalResource[@name='TMP']/@path" />
            </Variable>
        </Environment>
    </Task>
</Startup>

.NET 開發經驗

多重資料庫應用程式

下列範例程式碼使用熟悉的 .NET System.Transactions 程式設計經驗。 TransactionScope 類別會在 .NET 中建立環境交易 (「環境交易」是存在於目前執行緒中的交易。) 在 TransactionScope 中開啟的所有連線都會參與交易。 如果有不同的資料庫參與,交易會自動提升為分散式交易。 設定完成範圍來指出認可,即可控制交易的結果。

using (var scope = new TransactionScope())
{
    using (var conn1 = new SqlConnection(connStrDb1))
    {
        conn1.Open();
        SqlCommand cmd1 = conn1.CreateCommand();
        cmd1.CommandText = string.Format("insert into T1 values(1)");
        cmd1.ExecuteNonQuery();
    }
    using (var conn2 = new SqlConnection(connStrDb2))
    {
        conn2.Open();
        var cmd2 = conn2.CreateCommand();
        cmd2.CommandText = string.Format("insert into T2 values(2)");
        cmd2.ExecuteNonQuery();
    }
    scope.Complete();
}

分區化資料庫應用程式

SQL Database 和 SQL 受控執行個體的彈性資料庫交易也支援協調分散式交易,您可使用彈性資料庫用戶端程式庫的 OpenConnectionForKey 方法,開啟擴增資料層的連線。 假設變更跨數個不同分區化索引鍵值,而您需要保證交易一致性。 連接到裝載不同分區化索引鍵值的分區時,由 OpenConnectionForKey 代理連接。 在一般情況下可連接到不同分區,以確保交易保證需要分散式交易。 下列程式碼範例說明此方法。 其中假設使用一個稱為 shardmap 的變數,代表來自彈性資料庫用戶端程式庫的分區對應:

using (var scope = new TransactionScope())
{
    using (var conn1 = shardmap.OpenConnectionForKey(tenantId1, credentialsStr))
    {
        SqlCommand cmd1 = conn1.CreateCommand();
        cmd1.CommandText = string.Format("insert into T1 values(1)");
        cmd1.ExecuteNonQuery();
    }
    using (var conn2 = shardmap.OpenConnectionForKey(tenantId2, credentialsStr))
    {
        var cmd2 = conn2.CreateCommand();
        cmd2.CommandText = string.Format("insert into T1 values(2)");
        cmd2.ExecuteNonQuery();
    }
    scope.Complete();
}

Transact-SQL 開發經驗

使用 Transact-SQL 的伺服器端分散式交易僅適用於 Azure SQL 受控執行個體。 分散式交易只能在屬於相同伺服器信任群組的執行個體之間執行。 在此情節中,受控執行個體需要使用連結的伺服器來互相參考。

下列範例 Transact-SQL 程式碼使用 BEGIN DISTRIBUTED TRANSACTION 啟動分散式交易。

    -- Configure the Linked Server
    -- Add one Azure SQL Managed Instance as Linked Server
    EXEC sp_addlinkedserver
        @server='RemoteServer', -- Linked server name
        @srvproduct='',
        @provider='MSOLEDBSQL', -- Microsoft OLE DB Driver for SQL Server
        @datasrc='managed-instance-server.46e7afd5bc81.database.windows.net' -- SQL Managed Instance endpoint

    -- Add credentials and options to this Linked Server
    EXEC sp_addlinkedsrvlogin
        @rmtsrvname = 'RemoteServer', -- Linked server name
        @useself = 'false',
        @rmtuser = '<login_name>',         -- login
        @rmtpassword = '<secure_password>' -- password

    USE AdventureWorks2022;
    GO
    SET XACT_ABORT ON;
    GO
    BEGIN DISTRIBUTED TRANSACTION;
    -- Delete candidate from local instance.
    DELETE AdventureWorks2022.HumanResources.JobCandidate
        WHERE JobCandidateID = 13;
    -- Delete candidate from remote instance.
    DELETE RemoteServer.AdventureWorks2022.HumanResources.JobCandidate
        WHERE JobCandidateID = 13;
    COMMIT TRANSACTION;
    GO

結合 .NET 和 Transact-SQL 開發經驗

使用 System.Transaction 類別的 .NET 應用程式可以結合 TransactionScope 類別與 Transact-SQL 陳述式 BEGIN DISTRIBUTED TRANSACTION。 在 TransactionScope 中,執行 BEGIN DISTRIBUTED TRANSACTION 的內部交易會明確升階為分散式交易。 此外,當 TransactionScope 中開啟第二個 SqlConnecton 後,SqlConnecton 即會隱含升階為分散式交易。 啟動分散式交易後,所有後續的交易要求 (無論來自 .NET 或 Transact-SQL) 都會聯結父代分散式交易。 因此,BEGIN 陳述式起始的所有巢狀交易範圍最後會存在於同一個交易中,且 COMMIT/ROLLBACK 陳述式會對整體結果產生下列影響:

  • COMMIT 陳述式對 BEGIN 陳述式起始的交易範圍沒有任何影響,所以在 TransactionScope 物件上叫用 Complete() 方法前,不會有認可的結果。 如果在 TransactionScope 物件完成前將其終結,即會復原範圍內完成的所有變更。
  • ROLLBACK 陳述式會導致整個 TransactionScope 復原。 之後在 TransactionScope 中登錄新交易,及 TransactionScope 物件上叫用 Complete() 的任何嘗試都會失敗。

以下範例是使用 Transact-SQL 明確升階交易至分散式交易。

using (TransactionScope s = new TransactionScope())
{
    using (SqlConnection conn = new SqlConnection(DB0_ConnectionString)
    {
        conn.Open();
    
        // Transaction is here promoted to distributed by BEGIN statement
        //
        Helper.ExecuteNonQueryOnOpenConnection(conn, "BEGIN DISTRIBUTED TRAN");
        // ...
    }
 
    using (SqlConnection conn2 = new SqlConnection(DB1_ConnectionString)
    {
        conn2.Open();
        // ...
    }
    
    s.Complete();
}

下列範例顯示 TransactionScope 中啟動第二個 SqlConnecton 後,隱含升階為分散式交易的交易。

using (TransactionScope s = new TransactionScope())
{
    using (SqlConnection conn = new SqlConnection(DB0_ConnectionString)
    {
        conn.Open();
        // ...
    }
    
    using (SqlConnection conn = new SqlConnection(DB1_ConnectionString)
    {
        // Because this is second SqlConnection within TransactionScope transaction is here implicitly promoted distributed.
        //
        conn.Open(); 
        Helper.ExecuteNonQueryOnOpenConnection(conn, "BEGIN DISTRIBUTED TRAN");
        Helper.ExecuteNonQueryOnOpenConnection(conn, lsQuery);
        // ...
    }
    
    s.Complete();
}

SQL Database 的交易

支援跨 Azure SQL Database 不同伺服器間的彈性資料庫交易。 在交易跨伺服器的界限時,參與的伺服器首先必須加入相互的通訊關聯性。 一旦建立通訊關聯性之後,任一部伺服器中的任何資料庫都可以和另一部伺服器中的資料庫一起參與彈性交易。 如果是跨兩個以上伺服器的交易,任何一組伺服器都必須具備通訊關聯性。

使用下列 PowerShell Cmdlet 管理跨伺服器的通訊關聯性,以進行彈性資料庫交易:

  • New-AzSqlServerCommunicationLink:使用這個 Cmdlet 建立 Azure SQL Database 中兩部伺服器間的新通訊關聯性。 此關聯性是對稱的,也就是說,這兩部伺服器彼此都可以起始交易。
  • Get-AzSqlServerCommunicationLink:使用這個 Cmdlet 擷取現有的通訊關聯性和屬性。
  • Remove-AzSqlServerCommunicationLink:使用這個 Cmdlet 移除現有的通訊關聯性。

SQL 受控執行個體的交易

支援跨多個執行個體之資料庫的分散式交易。 當交易跨受控執行個體的界限時,參與的執行個體必須在相互的安全性和通訊關聯性中。 這可透過建立伺服器信任群組完成,即使用 Azure 入口網站或 Azure PowerShell 或 Azure CLI 完成。 如果執行個體不在相同的虛擬網路上,即須設定虛擬網路對等互連,同時網路安全性群組的輸入和輸出規則必須在所有參與的虛擬網路上允許連接埠 5024 和 11000-12000。

Server Trust Groups on Azure Portal

下圖顯示可使用 .NET 或 Transact-SQL 執行分散式交易的受控執行個體伺服器信任群組,:

Distributed transactions with Azure SQL Managed Instance using elastic transactions

監視交易狀態

使用動態管理檢視 (DMV) 監視進行中彈性資料庫交易的狀態和進度。 所有與交易相關的 DMV 都與 SQL Database 和 SQL 受控執行個體的分散式交易有關聯。 您可以在這裡找到對應的 DMV 清單: 交易相關的動態管理檢視和函數 (Transact-SQL)

這些 DMV 特別有用:

  • sys.dm_tran_active_transactions:列出目前作用中的交易和狀態。 UOW (工作單位) 資料行可以識別屬於相同分散式交易的不同子交易。 相同分散式交易內的所有交易具有相同的 UOW 值。 如需詳細資訊,請參閱 DMV 文件
  • sys.dm_tran_database_transactions:提供交易的其他資訊,例如交易在記錄檔中的位置。 如需詳細資訊,請參閱 DMV 文件
  • sys.dm_tran_locks:提供目前進行中交易所保有的鎖定相關資訊。 如需詳細資訊,請參閱 DMV 文件

限制

下列限制目前適用於 SQL Database 的彈性資料庫交易:

  • 僅支援 SQL Database 中跨資料庫的交易。 其他 X/Open XA 資源提供者和 SQL Database 之外的資料庫無法參與彈性資料庫交易。 這表示彈性資料庫交易無法延伸到內部部署 SQL Server 和 Azure SQL Database。 對於內部部署的分散式交易,請繼續使用 MSDTC。
  • 僅支援來自 .NET 應用程式的用戶端協調交易。 目前已規劃 T-SQL 的伺服器端支援,例如 BEGIN DISTRIBUTED TRANSACTION,但尚未推出。
  • 不支援跨 WCF 服務的交易。 例如,您有執行交易的 WCF 服務方法。 納入交易範圍內的呼叫將會失敗,因為 System.ServiceModel.ProtocolException

下列限制目前適用於「SQL 受控執行個體」中的分散式交易 (也稱為彈性交易或原生支援的分散式交易):

  • 使用此技術時,僅支援受控執行個體中跨資料庫的交易。 針對可能包括 X/Open XA 資源提供者以及 Azure SQL 受控執行個體外部資料庫的所有其他情節,您應該設定 Azure SQL 受控執行個體的 DTC
  • 不支援跨 WCF 服務的交易。 例如,您有執行交易的 WCF 服務方法。 納入交易範圍內的呼叫將會失敗,因為 System.ServiceModel.ProtocolException
  • Azure SQL 受控執行個體必須屬於伺服器信任群組,才能參與分散式交易。
  • 伺服器信任群組的限制會影響分散式交易。
  • 參與分散式交易的受控執行個體必須有私人端點的連線能力 (使用部署於虛擬網路的私人 IP 位址),並使用私人 FQDN 相互參考。 用戶端應用程式可以使用私人端點的分散式交易。 此外,如果 Transact-SQL 利用參考私人端點的連結伺服器,用戶端應用程式也可以在公用端點上使用分散式交易。 下圖將說明這項限制。

Private endpoint connectivity limitation

下一步