Распределенные транзакции по облачным базам данных

Применимо к:База данных SQL Azure Управляемый экземпляр SQL Azure

В этой статье описывается использование транзакций эластичной базы данных, которые позволяют выполнять распределенные транзакции между облачными базами данных для База данных SQL Azure и Управляемый экземпляр SQL Azure. В этой статье термины "распределенные транзакции" и "транзакции эластичной базы данных" считаются синонимами и используются взаимозаменяемо.

Примечание.

Вы также можете использовать координатор распределенных транзакций для Управляемый экземпляр SQL Azure для запуска распределенных транзакций в смешанных средах.

Обзор

Транзакции эластичных баз данных для базы данных SQL Azure и Управляемый экземпляр Azure SQL позволяют выполнять транзакции, охватывающие несколько баз данных. Транзакции эластичной базы данных доступны для приложений .NET, использующих ADO.NET. Кроме того, транзакции можно объединить с уже знакомыми приемами программирования, используя классы System.Transaction. Инструкции по подключению библиотеки см. в статье Microsoft .NET Framework 4.6.1 (веб-установщик) для Windows 7 SP1, Windows 8, Windows 8.1, Windows 10, Windows Server 2008 R2 SP1, Windows Server 2012 и Windows Server 2012 R2. Кроме того, в Transact-SQL доступны распределенные транзакции для управляемого экземпляра.

В локальной среде такой сценарий обычно требует запуска координатора распределенных транзакций Майкрософт (MSDTC). Так как MSDTC недоступен для База данных SQL Azure, возможность координации распределенных транзакций напрямую интегрирована в База данных SQL и Управляемый экземпляр SQL. Однако для Управляемый экземпляр SQL можно также использовать координатор распределенных транзакций для выполнения распределенных транзакций в нескольких смешанных средах, таких как в управляемых экземплярах, SQL Server, других системах управления реляционными базами данных (RDBMS), пользовательских приложениях и других участниках транзакций, размещенных в любой среде, которая может установить сетевое подключение к Azure.

Чтобы запустить распределенные транзакции, приложения можно подключить к любой базе данных. При этом одна из баз данных или один из серверов будет отвечать за прозрачную координацию распределенных транзакций, как показано на следующем рисунке.

Distributed transactions with Azure SQL Database using elastic database transactions

Распространенные сценарии

Транзакции эластичной базы данных позволяют вносить атомарные изменения в данные, хранящиеся в нескольких базах данных. Как База данных SQL, так и Управляемый экземпляр SQL поддерживают возможность разработки интерфейсов на стороне клиента на C# и .NET. Взаимодействие на стороне сервера (код, написанный в хранимых процедурах или серверных скриптах) с помощью Transact-SQL доступно только для Управляемого экземпляра SQL.

Важно!

Выполнение транзакций эластичной базы данных между Базой данных SQL Azure и Управляемым экземпляром SQL Azure не поддерживается. Транзакции эластичной базы данных могут охватывать только набор баз в Базе данных SQL или в управляемых экземплярах.

Транзакции эластичной базы данных применяются в следующих сценариях.

  • Приложения в Azure, использующие несколько баз данных. Этот сценарий предусматривает вертикальное секционирование данных между несколькими базами данных в базе данных SQL или в Управляемом экземпляре SQL. В результате разные виды данных находятся в разных базах данных. При выполнении некоторых операций необходимо вносить изменения в данные, которые хранятся в нескольких базах данных. Приложение использует транзакции эластичной базы данных для скоординированного внесения изменений в базах данных и обеспечения атомарности.
  • Приложения, использующие сегментированные базы данных. Этот сценарий предусматривает использование клиентской библиотеки эластичной базы данных или выполнения самостоятельного сегментирования для горизонтального разделения данных между несколькими базами данных в Базе данных SQL или в Управляемом экземпляре SQL. Первый пример использования заключается в необходимости внести атомарные изменения в сегментированное мультитенантное приложение, если изменения распространяются на клиенты. Например, рассмотрим передачу данных из одного клиента в другой, при этом оба клиента находятся в разных базах данных. Второй пример предполагает точное сегментирование в целях соблюдения требований к емкости для клиентов большого размера. В свою очередь, это обычно означает, что некоторые атомарные операции необходимо выполнять в нескольких базах данных, которые использует один клиент. Третий пример предусматривает атомарное обновление, обеспечивающее возможность ссылаться на данные, реплицируемые в базах данных. Теперь стала возможна координация атомарных транзакционных операций со всеми этими строками в нескольких базах данных. Транзакции эластичной базы данных используют двухфазную фиксацию для обеспечения атомарности транзакций в базах данных. Этот вариант прекрасно подходит для тех случаев, когда в одной транзакции одновременно участвует менее 100 баз данных. Эти ограничения не применяются принудительно, но следует учитывать, что их превышение отрицательно влияет на производительность и успешность выполнения транзакций эластичной базы данных.

Установка и миграция

Возможности для транзакций эластичной базы данных предоставляются с обновлениями библиотек .NET — System.Data.dll и System.Transactions.dll. Библиотеки DLL обеспечивают использование двухфазной фиксации для соблюдения атомарности. Чтобы начать разработку приложений, использующих транзакции эластичной базы данных, установите платформу .NET 4.6.1 или более поздней версии. При использовании платформы .NET предыдущей версии происходит ошибка повышения уровня транзакций до распределенных, после чего возникает исключение.

После установки можно использовать API распределенных транзакций в классах System.Transactions с подключением к Базе данных SQL и Управляемому экземпляру SQL. При наличии приложений MSDTC, использующих эти API, после установки платформы 4.6.1 просто повторно создайте существующие приложения .NET 4.6. Если ваши проекты предназначены для использования на платформе .NET 4.6, обновленные библиотеки DLL новой версии платформы будут использоваться автоматически, а вызовы API распределенных транзакций и подключения к Базе данных SQL или к Управляемому экземпляру SQL будут успешными.

Учтите, что для выполнения транзакций эластичной базы данных не требуется установка MSDTC. Вместо этого управление такими транзакциями осуществляется непосредственно в службе. Это значительно упрощает сценарии, в которых используется облако, так как для использования распределенных транзакций в Базе данных SQL и в управляемом экземпляре SQL не нужно развертывать MSDTC. В разделе 4 более подробно описано развертывание транзакций эластичной базы данных и требуемой платформы .NET вместе с облачными приложениями в Azure.

Установка .NET для облачных служб Azure

Azure включает несколько предложений для размещения приложений .NET. Сравнение различных предложений приведено в статье Сравнение службы приложений, облачных служб и виртуальных машин Azure. Если версия гостевой операционной системы предложения меньше .NET 4.6.1 (версия, необходимая для эластичных транзакций), необходимо обновить гостевую ОС до версии 4.6.1.

Для службы приложений Azure обновления гостевой ОС в настоящее время не поддерживаются. В виртуальных машинах Azure необходимо просто выполнить вход и запустить установщик для последней версии .NET Framework. Для облачных служб Azure необходимо включить установку более новой версии .NET в задачи запуска данного развертывания. Основные понятия и рекомендованные шаги см. в статье Установка .NET для роли облачной службы.

Обратите внимание на то, что в процессе начальной загрузки в облачных службах Azure для установки .NET 4.6.1 может потребоваться больше объема временного хранилища, чем для установки .NET 4.6. Для успешной установки необходимо увеличить временное хранилище для облачной службы Azure в разделе LocalResources файла ServiceDefinition.csdef и в параметрах среды для задачи запуска, как показано в следующем примере:

<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

Приложения, использующие несколько баз данных

В следующем примере кода знакомые приемы программирования используются в сочетании с System.Transactions .NET. Класс 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 и Управляемом экземпляре 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

Приложения .NET, использующие классы System. Transaction, могут сочетать класс TransactionScope с инструкцией Transact-SQL BEGIN DISTRIBUTED TRANSACTION. Внутри класса TransactionScope внутренняя транзакция, выполняющая инструкцию BEGIN DISTRIBUTED TRANSACTION, будет явно преобразована в распределенную транзакцию. Кроме того, при открытии второго SqlConnecton в TransactionScope он будет неявно выдвинут на распределенную транзакцию. После запуска распределенной транзакции все последующие запросы, поступающие от .NET или Transact-SQL, будут присоединяться к родительской распределенной транзакции. Как следствие, все вложенные области транзакций, инициированные инструкцией BEGIN, будут находиться в одной транзакции, а инструкции COMMIT и ROLLBACK будут влиять на общий результат:

  • Инструкция COMMIT не будет оказывать никакого воздействия на область транзакции, инициированную инструкцией BEGIN, то есть никакие результаты не будут зафиксированы перед вызовом метода Complete () для объекта TransactionScope. Если объект TransactionScope уничтожается до завершения, то выполняется откат всех изменений, выполненных в области.
  • Инструкция ROLLBACK приведет к откату всей TransactionScope. Любые попытки прикрепить новые транзакции в TransactionScope будут завершаться с ошибкой, а также попытаться вызвать метод Complete () для объекта TransactionScope.

Ниже приведен пример, в котором транзакция явно повышается до распределенной транзакции с помощью 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();
}

В следующем примере показана транзакция, которая неявно повышается до распределенной транзакции после запуска второй SqlConnecton в 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();
}

Транзакции для Базы данных SQL

Транзакции эластичной базы данных поддерживаются для разных серверов в Базе данных SQL Azure. Если транзакции пересекают границы сервера, для серверов-участников сначала необходимо настроить отношение взаимного обмена данными. После установления отношения взаимодействия любая база данных на любом из двух серверов может участвовать в эластичных транзакциях с базами данных другого сервера. Если транзакции охватывают более двух серверов, отношение взаимодействия необходимо настроить для каждой пары серверов.

Используйте следующие командлеты PowerShell для управления отношениями взаимодействия между серверами для транзакций эластичной базы данных:

  • New-AzSqlServerCommunicationLink: служит для создания нового отношения взаимодействия между двумя серверами в базе данных SQL Azure. Отношение симметрично, то есть оба сервера могут инициировать транзакции с другим сервером.
  • Get-AzSqlServerCommunicationLink: служит для получения существующих отношений взаимодействия и их свойств.
  • Remove-AzSqlServerCommunicationLink: служит для удаления существующих отношений взаимодействия.

Транзакции для Управляемого экземпляра 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

Мониторинг состояния транзакций

Используйте динамические административные представления для мониторинга состояния и хода выполнения текущих транзакций эластичных баз данных. Все представления, связанные с транзакциями, соответствуют Управляемому экземпляру SQL и распределенным транзакциям в Базе данных SQL. Соответствующий список динамических административных представлений можно найти здесь: Динамические административные представления и функции, связанные с транзакциями (Transact-SQL).

Особенно полезны следующие динамические административные представления.

  • sys.dm_tran_active_transactions — позволяет просматривать список активных транзакций и их состояние. В столбце UOW (единица работы) можно просмотреть различные дочерние транзакции, которые относятся к одной распределенной транзакции. У всех транзакций в рамках одной распределенной транзакции одинаковое значение UOW. Дополнительные сведения см. в документации по DMV.
  • sys.dm_tran_database_transactions — позволяет просматривать дополнительные сведения о транзакциях, включая расположение транзакции в журнале. Дополнительные сведения см. в документации по DMV.
  • sys.dm_tran_locks — в этом представлении содержатся сведения о текущих блокировках транзакций. Дополнительные сведения см. в документации по DMV.

Ограничения

В настоящее время в отношении транзакций эластичной базы данных в Базе данных SQL действует ряд ограничений.

  • Поддерживаются только транзакции, выполняемые между базами данных в базе данных SQL. В них не могут участвовать поставщики ресурсов и базы данных X или Open XA, которые не принадлежат к базе данных SQL. Это означает, что транзакции эластичной базы данных не могут растянуться в локальной среде SQL Server и База данных SQL Azure. Чтобы осуществлять распределенные транзакции локально, нужно использовать MSDTC.
  • Поддерживаются только транзакции, которые осуществляются с помощью приложения .NET и которые координирует клиент. Сейчас выполнение запросов T-SQL на серверах (например, BEGIN DISTRIBUTED TRANSACTION) не поддерживается, но в будущем мы планируем добавить эту возможность.
  • Транзакции между службами WCF не поддерживаются. Например, если у вас есть метод службы WCF, выполняющий транзакцию, включение вызова в область транзакции завершится ошибкой с исключением System.ServiceModel.ProtocolException.

Следующие ограничения в настоящее время применяются к распределенным транзакциям (также известным как эластичные транзакции или собственные поддерживаемые распределенные транзакции) в Управляемый экземпляр SQL:

  • Благодаря этой технологии поддерживаются только транзакции между базами данных в управляемых экземплярах. Для всех остальных сценариев, которые могут включать поставщиков ресурсов X/Open XA и базы данных за пределами Управляемый экземпляр SQL Azure следует настроить DTC для Управляемый экземпляр SQL Azure.
  • Транзакции между службами WCF не поддерживаются. Например, если у вас есть метод службы WCF, выполняющий транзакцию, включение вызова в область транзакции завершится ошибкой с исключением System.ServiceModel.ProtocolException.
  • Для участия в распределенной транзакции Управляемый экземпляр Azure SQL необходимо входить в группу доверия серверов.
  • Ограничения групп доверия серверов влияют на распределенные транзакции.
  • Управляемые экземпляры, участвующие в распределенных транзакциях, должны иметь возможность подключения через частные конечные точки (с использованием частного IP-адреса из виртуальной сети, где они развернуты) и должны быть взаимосвязаны с использованием частных полных доменных имен. Клиентские приложения могут использовать распределенные транзакции в частных конечных точках. Кроме того, в случаях, когда Transact-SQL использует связанные серверы, ссылающиеся на частные конечные точки, клиентские приложения могут также использовать распределенные транзакции на общедоступных конечных точках. Это ограничение объясняется на следующей схеме.

Private endpoint connectivity limitation

Следующие шаги