Gostaria de saber mais sobre o que acontece nos bastidores com uma transação de confirmação automática ao executar uma consulta entre servidores em um servidor vinculado.
Eu ingenuamente penso que, ao executar uma transação de confirmação automática, o compilador/SQL Server/outra coisa apenas precede todas as instruções com a BEGIN TRANSACTION
e anexa todas as instruções com a, COMMIT TRANSACTION
pois tudo está tecnicamente incluído em uma transação ( É uma prática ruim sempre criar uma transação ? ). Tenho certeza de que isso está incorreto e a fonte da minha confusão sobre por que executar um servidor cruzado UPDATE
sem declarar explicitamente BEGIN TRANSACTION
funciona, mas declarando explicitamente que não. De acordo com a Microsoft ( https://learn.microsoft.com/en-us/sql/t-sql/language-elements/begin-transaction-transact-sql?view=sql-server-2017 ), um explícito BEGIN TRANSACTION
sobre umUPDATE
a consulta que faz referência a uma tabela em um servidor vinculado é escalada para uma transação distribuída; e como as transações distribuídas não estão configuradas no servidor vinculado, recebo um erro. Como a configuração de confirmação automática evita isso? Como não é escalado para uma transação distribuída? A configuração de confirmação automática envia os dados para o servidor vinculado, mas não "escuta" uma resposta do servidor vinculado por meio do Microsoft Distributed Transaction Coordinator (MS DTC); assim, se ocorrer um erro, ele falha "silenciosamente"?
A confirmação automática não escala para uma transação distribuída:
UPDATE l
SET l.RecordKey = s.RecordKey
FROM LinkedServer.ExampleDatabase.dbo.ExampleTable AS l
INNER JOIN ServerWithActiveConnection.ExampleDatabase.dbo.ExampleTable AS s
ON l.Value1 = s.Value1;
A transação explícita escala para uma transação distribuída (e erros no meu caso):
BEGIN TRANSACTION
UPDATE l
SET l.RecordKey = s.RecordKey
FROM LinkedServer.ExampleDatabase.dbo.ExampleTable AS l
INNER JOIN ServerWithActiveConnection.ExampleDatabase.dbo.ExampleTable AS s
ON l.Value1 = s.Value1;
COMMIT TRANSACTION;
Devo acrescentar que as instruções foram executadas no SQL Server Management Studio.
Dado que um Linked Server é uma conexão externa/separada, eu esperaria que ele pudesse ser tratado/gerenciado separadamente, assim como fazer uma conexão externa/regular com qualquer SQL Server (mesmo de volta para a instância de chamada - ou seja, loop back) via
SqlClient
em SQLCLR. Sendo uma conexão separada, é opcional tentar ou não ingressar na transação atual (isso é tratado por meio da palavra-Enlist= {true | false}
chave da string de conexão). Estou supondo que a propriedade Linked Server deis_remote_proc_transaction_promotion_enabled
/ "Enable Promotion of Distributed Transactions for RPC" é equivalente à palavra-Enlist
chave da cadeia de conexão.Dito isto, há algo sendo esquecido (incluindo ser esquecido na minha resposta original): o nome dessa opção é "Ativar promoção de transações distribuídas para RPC " (ênfase minha). A parte destacada é bastante importante aqui. Essa opção afeta as chamadas de procedimento armazenado no servidor vinculado, não os lotes de consulta ad hoc regulares. Portanto, essa opção não deve ser relevante para o comportamento que você está descrevendo na pergunta.
Meu palpite (educado) é que, para consultas ad hoc, a opção "Inscrever-se" na transação atual é padronizada como "falsa" para transações de confirmação automática. Mas, para transações explícitas, você está dizendo ao SQL Server que todas as instruções dentro do
BEGIN TRAN ... COMMIT TRAN
devem ser consideradas uma operação atômica, então a conexão remota tenta se inscrever na transação atual.FYI: esse comportamento não deve ter nada a ver com a execução das instruções no SSMS. Isso é apenas um cliente que envia as instruções ao SQL Server para execução. Deve ser o mesmo comportamento mesmo se executado via SQLCMD.EXE ou
SqlCient
em um aplicativo .NET, etc.ATUALIZAR
Com relação a testar isso, sugeri ao OP usar o SQL Server Profiler ou Extended Events para capturar o alistamento / promoção da transação para transação distribuída. O OP respondeu com: