Distribuerade transaktioner över molndatabaser

Gäller för:Azure SQL DatabaseAzure SQL Managed Instance

Den här artikeln beskriver hur du använder elastiska databastransaktioner som gör att du kan köra distribuerade transaktioner över molndatabaser för Azure SQL Database och Azure SQL Managed Instance. I den här artikeln betraktas termerna "distribuerade transaktioner" och "elastiska databastransaktioner" som synonymer och används omväxlande.

Kommentar

Du kan också använda Distributed Transaction Coordinator för Azure SQL Managed Instance för att köra distribuerade transaktioner i blandade miljöer.

Översikt

Med elastiska databastransaktioner för Azure SQL Database och Azure SQL Managed Instance kan du köra transaktioner som omfattar flera databaser. Elastiska databastransaktioner är tillgängliga för .NET-program med ADO.NET och integrera med den välbekanta programmeringsupplevelsen med hjälp av System.Transaction-klasserna . Information om hur du hämtar biblioteket finns i .NET Framework 4.6.1 (Webbinstallation). Dessutom är distribuerade transaktioner för hanterade instanser tillgängliga i Transact-SQL.

Lokalt kräver ett sådant scenario vanligtvis att Microsoft Distributed Transaction Coordinator (MSDTC) körs. Eftersom MSDTC inte är tillgängligt för Azure SQL Database har möjligheten att samordna distribuerade transaktioner integrerats direkt i SQL Database och SQL Managed Instance. För SQL Managed Instance kan du dock också använda Koordinator för distribuerade transaktioner i ett antal blandade miljöer, till exempel mellan hanterade instanser, SQL-servrar, andra hanteringssystem för relationsdatabaser (RDBMS), anpassade program och andra transaktionsdeltagare som finns i alla miljöer som kan upprätta nätverksanslutningar till Azure.

Program kan ansluta till valfri databas för att starta distribuerade transaktioner, och en av databaserna eller servrarna samordnar transparent den distribuerade transaktionen, enligt följande bild.

Distributed transactions with Azure SQL Database using elastic database transactions

Vanliga scenarier

Med transaktioner med elastiska databaser kan program göra atomiska ändringar i data som lagras i flera olika databaser. Både SQL Database och SQL Managed Instance stöder utvecklingsupplevelser på klientsidan i C# och .NET. En upplevelse på serversidan (kod som skrivits i lagrade procedurer eller skript på serversidan) med Transact-SQL är endast tillgänglig för SQL Managed Instance.

Viktigt!

Det går inte att köra elastiska databastransaktioner mellan Azure SQL Database och Azure SQL Managed Instance. Elastisk databastransaktion kan bara sträcka sig över en uppsättning databaser i SQL Database eller en uppsättning databaser över hanterade instanser.

Elastiska databastransaktioner är inriktade på följande scenarier:

  • Program med flera databaser i Azure: I det här scenariot partitioneras data vertikalt över flera databaser i SQL Database eller SQL Managed Instance, så att olika typer av data finns i olika databaser. Vissa åtgärder kräver ändringar i data, som sparas i två eller flera databaser. Programmet använder elastiska databastransaktioner för att samordna ändringarna mellan databaser och säkerställa atomitet.
  • Sharded Database-program i Azure: I det här scenariot använder datanivån Elastic Database-klientbiblioteket eller självpartitionering för att horisontellt partitionera data över många databaser i SQL Database eller SQL Managed Instance. Ett framträdande användningsfall är behovet av att utföra atomiska ändringar för ett fragmenterat program med flera klientorganisationer när ändringarna omfattar klientorganisationer. Tänk på en överföring från en klientorganisation till en annan, som båda finns i olika databaser. Ett andra fall är detaljerad horisontell partitionering för att tillgodose kapacitetsbehov för en stor klientorganisation, vilket i sin tur vanligtvis innebär att vissa atomiska åtgärder måste sträcka sig över flera databaser som används för samma klientorganisation. Ett tredje fall är atomiska uppdateringar av referensdata som replikeras mellan databaser. Atomiska, transacted, åtgärder längs dessa linjer kan nu samordnas över flera databaser. Elastiska databastransaktioner använder två faser för att säkerställa transaktions atomicitet mellan databaser. Det passar bra för transaktioner som omfattar färre än 100 databaser åt gången inom en enda transaktion. Dessa gränser tillämpas inte, men man bör förvänta sig prestanda och framgångsgrader för elastiska databastransaktioner när de överskrider dessa gränser.

Installation och migrering

Funktionerna för elastiska databastransaktioner tillhandahålls via uppdateringar av .NET-biblioteken System.Data.dll och System.Transactions.dll. DLL:erna ser till att tvåfasincheckning används vid behov för att säkerställa atomitet. Om du vill börja utveckla program med elastiska databastransaktioner installerar du .NET Framework 4.6.1 eller en senare version. När du kör på en tidigare version av .NET-ramverket kan transaktioner inte befordras till en distribuerad transaktion och ett undantag genereras.

Efter installationen kan du använda de distribuerade transaktions-API:erna i System.Transactions med anslutningar till SQL Database och SQL Managed Instance. Om du har befintliga MSDTC-program som använder dessa API:er återskapar du dina befintliga program för .NET 4.6 när du har installerat 4.6.1 Framework. Om dina projekt riktar in sig på .NET 4.6 använder de automatiskt de uppdaterade DLL:erna från den nya Framework-versionen och distribuerade transaktions-API-anrop i kombination med anslutningar till SQL Database eller SQL Managed Instance kommer nu att lyckas.

Kom ihåg att elastiska databastransaktioner inte kräver installation av MSDTC. I stället hanteras elastiska databastransaktioner direkt av och inom tjänsten. Detta förenklar molnscenarier avsevärt eftersom en distribution av MSDTC inte behövs för att använda distribuerade transaktioner med SQL Database eller SQL Managed Instance. Avsnitt 4 beskriver mer detaljerat hur du distribuerar transaktioner med elastiska databaser och det nödvändiga .NET-ramverket tillsammans med dina molnprogram till Azure.

.NET-installation för Azure Cloud Services

Azure tillhandahåller flera erbjudanden för att vara värd för .NET-program. En jämförelse av de olika erbjudandena finns i jämförelsen mellan Azure App Service, Cloud Services och Virtual Machines. Om gästoperativsystemet för erbjudandet är mindre än .NET 4.6.1 som krävs för elastiska transaktioner måste du uppgradera gästoperativsystemet till 4.6.1.

För Azure App Service stöds för närvarande inte uppgraderingar till gästoperativsystemet. För virtuella Azure-datorer loggar du bara in på den virtuella datorn och kör installationsprogrammet för det senaste .NET-ramverket. För Azure Cloud Services måste du inkludera installationen av en nyare .NET-version i startuppgifterna för distributionen. Begreppen och stegen dokumenteras i Installera .NET på en molntjänstroll.

Observera att installationsprogrammet för .NET 4.6.1 kan kräva mer tillfällig lagring under startprocessen i Azure-molntjänster än installationsprogrammet för .NET 4.6. För att säkerställa en lyckad installation måste du öka det tillfälliga lagringsutrymmet för azure-molntjänsten i filen ServiceDefinition.csdef i avsnittet LocalResources och miljöinställningarna för startuppgiften, som du ser i följande exempel:

<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-utvecklingsupplevelse

Program med flera databaser

Följande exempelkod använder den välbekanta programmeringsupplevelsen med .NET System.Transactions. Klassen TransactionScope upprättar en omgivande transaktion i .NET. (En "omgivande transaktion" är en transaktion som finns i den aktuella tråden.) Alla anslutningar som öppnas i TransactionScope deltar i transaktionen. Om olika databaser deltar utökas transaktionen automatiskt till en distribuerad transaktion. Resultatet av transaktionen styrs genom att ange omfånget som ska slutföras för att indikera en incheckning.

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();
}

Fragmenterade databasprogram

Elastiska databastransaktioner för SQL Database och SQL Managed Instance stöder också samordning av distribuerade transaktioner där du använder metoden Open Anslut ionForKey i klientbiblioteket för elastisk databas för att öppna anslutningar för en utskalad datanivå. Överväg fall där du behöver garantera transaktionskonsekvens för ändringar i flera olika nyckelvärden för horisontell partitionering. Anslut joner till shards som är värdar för de olika värdena för partitioneringsnyckeln asynkronas med hjälp av Open Anslut ionForKey. I det allmänna fallet kan anslutningarna vara till olika shards, så att säkerställande av transaktionsgarantier kräver en distribuerad transaktion. Följande kodexempel illustrerar den här metoden. Det förutsätter att en variabel som kallas shardmap används för att representera en fragmentkarta från klientbiblioteket för elastisk databas:

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-utveckling

Distribuerade transaktioner på serversidan med Transact-SQL är endast tillgängliga för Azure SQL Managed Instance. Distribuerad transaktion kan endast köras mellan instanser som tillhör samma serverförtroendegrupp. I det här scenariot måste hanterade instanser använda länkad server för att referera till varandra.

Följande exempel på Transact-SQL-kod använder BEGIN DISTRIBUTED TRANSACTION för att starta distribuerade transaktioner.

    -- 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

Kombinera .NET- och Transact-SQL-utvecklingsupplevelsen

.NET-program som använder System.Transaction-klasser kan kombinera TransactionScope-klassen med Transact-SQL-instruktionen BEGIN DISTRIBUTED TRANSACTION. Inom TransactionScope befordras den inre transaktion som kör BEGIN DISTRIBUTED TRANSACTION explicit till distribuerad transaktion. När den andra Sql Anslut on öppnas i TransactionScope kommer den dessutom implicit att befordras till distribuerad transaktion. När distribuerade transaktioner har startats ansluter alla efterföljande transaktionsbegäranden, oavsett om de kommer från .NET eller Transact-SQL, till den överordnade distribuerade transaktionen. Därför kommer alla kapslade transaktionsomfattningar som initieras av BEGIN-instruktionen att hamna i samma transaktion och COMMIT/ROLLBACK-instruktioner kommer att ha följande effekt på det övergripande resultatet:

  • COMMIT-instruktionen kommer inte att ha någon effekt på transaktionsomfånget som initieras av BEGIN-instruktionen, d.v.s. inga resultat kommer att bekräftas innan Metoden Complete() anropas på TransactionScope-objektet. Om TransactionScope-objektet förstörs innan det slutförs återställs alla ändringar som görs i omfånget.
  • ROLLBACK-instruktionen gör att hela TransactionScope återställs. Alla försök att registrera nya transaktioner i TransactionScope misslyckas efteråt, samt försök att anropa Complete() på TransactionScope-objektet.

Här är ett exempel där transaktionen uttryckligen befordras till distribuerad transaktion med 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();
}

I följande exempel visas en transaktion som implicit befordras till distribuerad transaktion när den andra Sql Anslut on startades i TransactionScope.

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();
}

Transaktioner för SQL Database

Elastiska databastransaktioner stöds på olika servrar i Azure SQL Database. När transaktioner korsar servergränser måste de deltagande servrarna först ingå i en ömsesidig kommunikationsrelation. När kommunikationsrelationen har upprättats kan alla databaser på någon av de två servrarna delta i elastiska transaktioner med databaser från den andra servern. Med transaktioner som sträcker sig över fler än två servrar måste en kommunikationsrelation finnas på plats för valfritt par servrar.

Använd följande PowerShell-cmdletar för att hantera kommunikationsrelationer mellan servrar för elastiska databastransaktioner:

  • New-AzSqlServerCommunicationLink: Använd den här cmdleten för att skapa en ny kommunikationsrelation mellan två servrar i Azure SQL Database. Relationen är symmetrisk, vilket innebär att båda servrarna kan initiera transaktioner med den andra servern.
  • Get-AzSqlServerCommunicationLink: Använd den här cmdleten för att hämta befintliga kommunikationsrelationer och deras egenskaper.
  • Remove-AzSqlServerCommunicationLink: Använd den här cmdleten för att ta bort en befintlig kommunikationsrelation.

Transaktioner för SQL Managed Instance

Distribuerade transaktioner stöds i flera databaser i flera instanser. När transaktioner överskrider gränserna för hanterade instanser måste de deltagande instanserna ha en ömsesidig säkerhets- och kommunikationsrelation. Detta görs genom att skapa en serverförtroendegrupp, vilket kan göras med hjälp av Azure-portalen eller Azure PowerShell eller Azure CLI. Om instanser inte finns i samma virtuella nätverk måste du konfigurera peering för virtuella nätverk och regler för nätverkssäkerhetsgrupp för inkommande och utgående trafik måste tillåta portarna 5024 och 11000-12000 på alla deltagande virtuella nätverk.

Server Trust Groups on Azure Portal

Följande diagram visar en serverförtroendegrupp med hanterade instanser som kan köra distribuerade transaktioner med .NET eller Transact-SQL:

Distributed transactions with Azure SQL Managed Instance using elastic transactions

Övervaka transaktionsstatus

Använd dynamiska hanteringsvyer (DMV:er) för att övervaka status och förlopp för dina pågående elastiska databastransaktioner. Alla DMV:er som är relaterade till transaktioner är relevanta för distribuerade transaktioner i SQL Database och SQL Managed Instance. Du hittar motsvarande lista över DMV:er här: Transaktionsrelaterade dynamiska hanteringsvyer och funktioner (Transact-SQL).

Dessa DMV:er är särskilt användbara:

  • sys.dm_tran_active_transactions: Visar en lista över aktiva transaktioner och deras status. Kolumnen UOW (Arbetsenhet) kan identifiera de olika underordnade transaktioner som tillhör samma distribuerade transaktion. Alla transaktioner inom samma distribuerade transaktion har samma UOW-värde. Mer information finns i DMV-dokumentationen.
  • sys.dm_tran_database_transactions: Innehåller ytterligare information om transaktioner, till exempel placering av transaktionen i loggen. Mer information finns i DMV-dokumentationen.
  • sys.dm_tran_locks: Innehåller information om de lås som för närvarande innehas av pågående transaktioner. Mer information finns i DMV-dokumentationen.

Begränsningar

Följande begränsningar gäller för elastiska databastransaktioner i SQL Database:

  • Endast transaktioner mellan databaser i SQL Database stöds. Andra X/Open XA-resursproviders och databaser utanför SQL Database kan inte delta i transaktioner med elastiska databaser. Det innebär att elastiska databastransaktioner inte kan sträcka sig över lokal SQL Server och Azure SQL Database. För distribuerade transaktioner lokalt fortsätter du att använda MSDTC.
  • Endast klientkoordinerade transaktioner från ett .NET-program stöds. Stöd på serversidan för T-SQL, till exempel BEGIN DISTRIBUTED TRANSACTION, planeras, men är ännu inte tillgängligt.
  • Transaktioner mellan WCF-tjänster stöds inte. Du har till exempel en WCF-tjänstmetod som kör en transaktion. Om du omsluter anropet inom ett transaktionsomfång misslyckas det som system.ServiceModel.ProtocolException.

Följande begränsningar gäller för närvarande för distribuerade transaktioner (kallas även elastiska transaktioner eller internt stödda distribuerade transaktioner) i SQL Managed Instance:

  • Med den här tekniken stöds endast transaktioner mellan databaser i hanterade instanser. För alla andra scenarier som kan omfatta X/Open XA-resursproviders och databaser utanför Azure SQL Managed Instance bör du konfigurera DTC för Azure SQL Managed Instance.
  • Transaktioner mellan WCF-tjänster stöds inte. Du har till exempel en WCF-tjänstmetod som kör en transaktion. Om du omsluter anropet inom ett transaktionsomfång misslyckas det som system.ServiceModel.ProtocolException.
  • Azure SQL Managed Instance måste ingå i en serverförtroendegrupp för att kunna delta i distribuerade transaktioner.
  • Begränsningar för serverförtroendegrupper påverkar distribuerade transaktioner.
  • Hanterade instanser som deltar i distribuerade transaktioner måste ha anslutning via privata slutpunkter (med privat IP-adress från det virtuella nätverk där de distribueras) och måste refereras ömsesidigt med hjälp av privata FQDN. Klientprogram kan använda distribuerade transaktioner på privata slutpunkter. Dessutom kan klientprogram även använda distribuerade transaktioner på offentliga slutpunkter när Transact-SQL använder länkade servrar som refererar till privata slutpunkter. Den här begränsningen förklaras i följande diagram.

Private endpoint connectivity limitation

Nästa steg