Transações distribuídas entre bases de dados de cloud
Aplica-se a:Banco de Dados SQL do Azure Instância Gerenciada SQLdo Azure
Este artigo descreve o uso de transações de banco de dados elástico que permitem executar transações distribuídas entre bancos de dados em nuvem para o Banco de Dados SQL do Azure e a Instância Gerenciada SQL do Azure. Neste artigo, os termos "transações distribuídas" e "transações de banco de dados elástico" são considerados sinônimos e são usados indistintamente.
Nota
Você também pode usar o Coordenador de Transações Distribuídas para Instância Gerenciada SQL do Azure para executar transações distribuídas em ambientes mistos.
Descrição geral
As transações de banco de dados elástico para o Banco de Dados SQL do Azure e a Instância Gerenciada SQL do Azure permitem executar transações que abrangem vários bancos de dados. As transações de banco de dados elástico estão disponíveis para aplicativos .NET usando ADO.NET e integram-se com a experiência de programação familiar usando as classes System.Transaction . Para obter a biblioteca, consulte .NET Framework 4.6.1 (Web Installer). Além disso, para a instância gerida, as transações distribuídas estão disponíveis no Transact-SQL.
No local, esse cenário geralmente requer a execução do Microsoft Distributed Transaction Coordinator (MSDTC). Como o MSDTC não está disponível para o Banco de Dados SQL do Azure, a capacidade de coordenar transações distribuídas foi integrada diretamente ao Banco de Dados SQL e à Instância Gerenciada do SQL. No entanto, para a Instância Gerenciada SQL, você também pode usar o Coordenador de Transações Distribuídas para executar transações distribuídas em vários ambientes mistos, como instâncias gerenciadas, SQL Servers, outros sistemas de gerenciamento de banco de dados relacional (RDBMSs), aplicativos personalizados e outros participantes de transações hospedados em qualquer ambiente que possa estabelecer conectividade de rede com o Azure.
Os aplicativos podem se conectar a qualquer banco de dados para iniciar transações distribuídas, e um dos bancos de dados ou servidores coordenará de forma transparente a transação distribuída, conforme mostrado na figura a seguir.
Cenários comuns
As transações de banco de dados elástico permitem que os aplicativos façam alterações atômicas nos dados armazenados em vários bancos de dados diferentes. O Banco de Dados SQL e a Instância Gerenciada SQL oferecem suporte a experiências de desenvolvimento do lado do cliente em C# e .NET. Uma experiência do lado do servidor (código escrito em procedimentos armazenados ou scripts do lado do servidor) usando Transact-SQL está disponível apenas para a Instância Gerenciada do SQL .
Importante
Não há suporte para a execução de transações de banco de dados elástico entre o Banco de Dados SQL do Azure e a Instância Gerenciada SQL do Azure. A transação de banco de dados elástico só pode abranger um conjunto de bancos de dados no Banco de dados SQL ou um conjunto de bancos de dados em instâncias gerenciadas.
As transações de banco de dados elástico destinam-se aos seguintes cenários:
- Aplicativos de vários bancos de dados no Azure: com esse cenário, os dados são particionados verticalmente em vários bancos de dados no Banco de Dados SQL ou na Instância Gerenciada do SQL, de modo que diferentes tipos de dados residam em bancos de dados diferentes. Algumas operações exigem alterações nos dados, que são mantidos em dois ou mais bancos de dados. O aplicativo usa transações de banco de dados elástico para coordenar as alterações entre bancos de dados e garantir a atomicidade.
- Aplicativos de banco de dados fragmentados no Azure: com esse cenário, a camada de dados usa a biblioteca de cliente do Banco de Dados Elástico ou a autofragmentação para particionar horizontalmente os dados em vários bancos de dados no Banco de Dados SQL ou na Instância Gerenciada do SQL. Um caso de uso proeminente é a necessidade de executar alterações atômicas para um aplicativo multilocatário fragmentado quando as alterações abrangem locatários. Pense, por exemplo, numa transferência de um inquilino para outro, ambos residindo em bases de dados diferentes. Um segundo caso é a fragmentação refinada para acomodar as necessidades de capacidade de um locatário grande, o que, por sua vez, normalmente implica que algumas operações atômicas precisam se estender por vários bancos de dados usados para o mesmo locatário. Um terceiro caso são as atualizações atômicas para dados de referência que são replicados em bancos de dados. As operações atómicas, transacionadas, neste sentido, podem agora ser coordenadas em várias bases de dados. As transações de banco de dados elástico usam confirmação em duas fases para garantir a atomicidade das transações entre bancos de dados. É uma boa opção para transações que envolvem menos de 100 bancos de dados por vez em uma única transação. Esses limites não são impostos, mas deve-se esperar que as taxas de desempenho e sucesso para transações de banco de dados elástico sofram ao exceder esses limites.
Instalação e migração
Os recursos para transações de banco de dados elástico são fornecidos por meio de atualizações para as bibliotecas .NET System.Data.dll e System.Transactions.dll. As DLLs garantem que a confirmação em duas fases seja usada quando necessário para garantir a atomicidade. Para começar a desenvolver aplicativos usando transações de banco de dados elástico, instale o .NET Framework 4.6.1 ou uma versão posterior. Quando executado em uma versão anterior do .NET framework, as transações falharão ao promover para uma transação distribuída e uma exceção será gerada.
Após a instalação, você pode usar as APIs de transação distribuída em System.Transactions com conexões com o Banco de Dados SQL e a Instância Gerenciada SQL. Se você tiver aplicativos MSDTC existentes usando essas APIs, recrie seus aplicativos existentes para .NET 4.6 depois de instalar o 4.6.1 Framework. Se seus projetos tiverem como destino o .NET 4.6, eles usarão automaticamente as DLLs atualizadas da nova versão do Framework e as chamadas de API de transação distribuída em combinação com conexões com o Banco de dados SQL ou a Instância Gerenciada do SQL serão bem-sucedidas.
Lembre-se de que as transações de banco de dados elástico não exigem a instalação do MSDTC. Em vez disso, as transações de banco de dados elástico são gerenciadas diretamente pelo serviço e dentro dele. Isso simplifica significativamente os cenários de nuvem, uma vez que uma implantação do MSDTC não é necessária para usar transações distribuídas com o Banco de Dados SQL ou a Instância Gerenciada SQL. A Seção 4 explica com mais detalhes como implantar transações de banco de dados elástico e a estrutura .NET necessária junto com seus aplicativos de nuvem no Azure.
Instalação do .NET para Serviços de Nuvem do Azure
O Azure fornece várias ofertas para hospedar aplicativos .NET. Uma comparação das diferentes ofertas está disponível na comparação do Serviço de Aplicativo do Azure, Serviços de Nuvem e Máquinas Virtuais. Se o SO convidado da oferta for menor do que o .NET 4.6.1 necessário para transações elásticas, você precisará atualizar o SO convidado para 4.6.1.
Para o Serviço de Aplicativo do Azure, as atualizações para o SO convidado não são suportadas no momento. Para Máquinas Virtuais do Azure, basta fazer logon na VM e executar o instalador para o .NET Framework mais recente. Para os Serviços de Nuvem do Azure, você precisa incluir a instalação de uma versão mais recente do .NET nas tarefas de inicialização de sua implantação. Os conceitos e etapas estão documentados em Instalar o .NET em uma função de serviço de nuvem.
Observe que o instalador do .NET 4.6.1 pode exigir mais armazenamento temporário durante o processo de inicialização nos serviços de nuvem do Azure do que o instalador do .NET 4.6. Para garantir uma instalação bem-sucedida, você precisa aumentar o armazenamento temporário para seu serviço de nuvem do Azure em seu arquivo ServiceDefinition.csdef na seção LocalResources e as configurações de ambiente de sua tarefa de inicialização, conforme mostrado no exemplo a seguir:
<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>
Experiência em desenvolvimento .NET
Aplicações com várias bases de dados
O código de exemplo a seguir usa a experiência de programação familiar com .NET System.Transactions. A classe TransactionScope estabelece uma transação de ambiente no .NET. (Uma "transação ambiente" é aquela que vive no segmento atual.) Todas as conexões abertas dentro do TransactionScope participam da transação. Se diferentes bancos de dados participarem, a transação será automaticamente elevada a uma transação distribuída. O resultado da transação é controlado definindo o escopo a ser concluído para indicar um compromisso.
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();
}
Aplicativos de banco de dados fragmentados
As transações de banco de dados elástico para Banco de dados SQL e Instância Gerenciada SQL também oferecem suporte à coordenação de transações distribuídas em que você usa o método OpenConnectionForKey da biblioteca cliente de banco de dados elástico para abrir conexões para uma camada de dados dimensionada. Considere os casos em que você precisa garantir a consistência transacional para alterações em vários valores de chave de fragmentação diferentes. As conexões com os fragmentos que hospedam os diferentes valores de chave de fragmentação são intermediadas usando OpenConnectionForKey. No caso geral, as conexões podem ser com diferentes fragmentos, de modo que garantir garantias transacionais requer uma transação distribuída. O exemplo de código a seguir ilustra essa abordagem. Ele assume que uma variável chamada shardmap é usada para representar um mapa de estilhaços da biblioteca cliente do banco de dados elástico:
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();
}
Experiência de desenvolvimento Transact-SQL
As transações distribuídas do lado do servidor usando o Transact-SQL estão disponíveis apenas para a Instância Gerenciada SQL do Azure. A transação distribuída só pode ser executada entre instâncias que pertencem ao mesmo grupo de confiança do servidor. Nesse cenário, as instâncias gerenciadas precisam usar o servidor vinculado para fazer referência umas às outras.
O código Transact-SQL de exemplo a seguir usa BEGIN DISTRIBUTED TRANSACTION para iniciar a transação distribuída.
-- 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
Combinando a experiência de desenvolvimento .NET e Transact-SQL
Os aplicativos .NET que usam classes System.Transaction podem combinar a classe TransactionScope com a instrução Transact-SQL BEGIN DISTRIBUTED TRANSACTION. Dentro do TransactionScope, a transação interna que executa BEGIN DISTRIBUTED TRANSACTION será explicitamente promovida para transação distribuída. Além disso, quando o segundo SqlConnecton é aberto dentro do TransactionScope, ele será implicitamente promovido para transação distribuída. Depois que a transação distribuída for iniciada, todas as solicitações de transações subsequentes, sejam elas provenientes do .NET ou do Transact-SQL, ingressarão na transação distribuída pai. Como consequência, todos os escopos de transação aninhados iniciados pela instrução BEGIN terminarão na mesma transação e as instruções COMMIT/ROLLBACK terão o seguinte efeito no resultado geral:
- A instrução COMMIT não terá qualquer efeito sobre o escopo da transação iniciada pela instrução START, ou seja, nenhum resultado será confirmado antes que o método Complete() seja invocado no objeto TransactionScope. Se o objeto TransactionScope for destruído antes de ser concluído, todas as alterações feitas dentro do escopo serão revertidas.
- A instrução ROLLBACK fará com que todo o TransactionScope seja revertido. Qualquer tentativa de inscrever novas transações dentro de TransactionScope falhará posteriormente, bem como tentará invocar Complete() no objeto TransactionScope.
Aqui está um exemplo em que a transação é explicitamente promovida para transação distribuída com o 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();
}
O exemplo a seguir mostra uma transação que é implicitamente promovida para transação distribuída depois que o segundo SqlConnecton foi iniciado dentro do 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();
}
Transações para o Banco de Dados SQL
As transações de banco de dados elástico têm suporte em diferentes servidores no Banco de Dados SQL do Azure. Quando as transações cruzam os limites do servidor, os servidores participantes primeiro precisam ser inseridos em uma relação de comunicação mútua. Uma vez estabelecida a relação de comunicação, qualquer banco de dados em qualquer um dos dois servidores pode participar de transações elásticas com bancos de dados do outro servidor. Com transações que abrangem mais de dois servidores, uma relação de comunicação precisa estar em vigor para qualquer par de servidores.
Use os seguintes cmdlets do PowerShell para gerenciar relações de comunicação entre servidores para transações de banco de dados elástico:
- New-AzSqlServerCommunicationLink: use este cmdlet para criar uma nova relação de comunicação entre dois servidores no Banco de Dados SQL do Azure. A relação é simétrica, o que significa que ambos os servidores podem iniciar transações com o outro servidor.
- Get-AzSqlServerCommunicationLink: use este cmdlet para recuperar relações de comunicação existentes e suas propriedades.
- Remove-AzSqlServerCommunicationLink: use este cmdlet para remover uma relação de comunicação existente.
Transações para instância gerenciada SQL
As transações distribuídas são suportadas entre bancos de dados em várias instâncias. Quando as transações ultrapassam os limites das instâncias geridas, as instâncias participantes têm de estar numa relação de segurança e comunicação mútua. Isso é feito criando um Grupo de Confiança do Servidor, que pode ser feito usando o portal do Azure ou o Azure PowerShell ou a CLI do Azure. Se as instâncias não estiverem na mesma rede virtual, você deverá configurar o emparelhamento de rede virtual e as regras de entrada e saída do grupo de segurança de rede precisarão permitir as portas 5024 e 11000-12000 em todas as redes virtuais participantes.
O diagrama a seguir mostra um Grupo de Confiança do Servidor com instâncias gerenciadas que podem executar transações distribuídas com .NET ou Transact-SQL:
Monitorando o status da transação
Use as Exibições de Gerenciamento Dinâmico (DMVs) para monitorar o status e o progresso de suas transações de banco de dados elástico em andamento. Todos os DMVs relacionados a transações são relevantes para transações distribuídas no Banco de Dados SQL e na Instância Gerenciada SQL. Você pode encontrar a lista correspondente de DMVs aqui: Exibições e funções de gerenciamento dinâmico relacionadas a transações (Transact-SQL).
Estes DMVs são particularmente úteis:
- sys.dm_tran_ative_transactions: Lista as transações ativas no momento e seu status. A coluna UOW (Unidade de Trabalho) pode identificar as diferentes transações filho que pertencem à mesma transação distribuída. Todas as transações dentro da mesma transação distribuída têm o mesmo valor UOW. Para obter mais informações, consulte a documentação do Detran.
- sys.dm_tran_database_transactions: Fornece informações adicionais sobre transações, como o posicionamento da transação no log. Para obter mais informações, consulte a documentação do Detran.
- sys.dm_tran_locks: Fornece informações sobre os bloqueios que são atualmente mantidos por transações em andamento. Para obter mais informações, consulte a documentação do Detran.
Limitações
Atualmente, as seguintes limitações se aplicam a transações de banco de dados elástico no Banco de dados SQL:
- Somente transações entre bancos de dados no Banco de dados SQL são suportadas. Outros provedores de recursos X/Open XA e bancos de dados fora do Banco de dados SQL não podem participar de transações de banco de dados elástico. Isso significa que as transações de banco de dados elástico não podem se estender entre o SQL Server local e o Banco de Dados SQL do Azure. Para transações distribuídas no local, continue a usar o MSDTC.
- Somente transações coordenadas pelo cliente de um aplicativo .NET são suportadas. O suporte do lado do servidor para T-SQL, como BEGIN DISTRIBUTED TRANSACTION, está planejado, mas ainda não está disponível.
- Não há suporte para transações entre serviços WCF. Por exemplo, você tem um método de serviço WCF que executa uma transação. Incluir a chamada dentro de um escopo de transação falhará como um System.ServiceModel.ProtocolException.
Atualmente, as limitações a seguir se aplicam a transações distribuídas (também conhecidas como transações elásticas ou transações distribuídas com suporte nativo) na Instância Gerenciada SQL:
- Com essa tecnologia, apenas transações entre bancos de dados em instâncias gerenciadas são suportadas. Para todos os outros cenários que podem incluir provedores de recursos X/Open XA e bancos de dados fora da Instância Gerenciada SQL do Azure, você deve configurar o DTC para a Instância Gerenciada SQL do Azure.
- Não há suporte para transações entre serviços WCF. Por exemplo, você tem um método de serviço WCF que executa uma transação. Incluir a chamada dentro de um escopo de transação falhará como um System.ServiceModel.ProtocolException.
- A Instância Gerenciada SQL do Azure deve fazer parte de um grupo de confiança do Servidor para participar da transação distribuída.
- As limitações dos grupos de confiança do servidor afetam as transações distribuídas.
- As instâncias gerenciadas que participam de transações distribuídas precisam ter conectividade sobre pontos de extremidade privados (usando o endereço IP privado da rede virtual onde são implantadas) e precisam ser referenciadas mutuamente usando FQDNs privados. Os aplicativos cliente podem usar transações distribuídas em pontos de extremidade privados. Além disso, nos casos em que o Transact-SQL aproveita servidores vinculados fazendo referência a pontos de extremidade privados, os aplicativos cliente também podem usar transações distribuídas em pontos de extremidade públicos. Esta limitação é explicada no diagrama seguinte.