MSDTC Internals

Essa semana me surpreendi com o SQL Saturday #325 . Fiquei tão empolgado que resolvi investir um tempo para escrever esse post. A escolha do tema foi através de uma conversa no twitter. Obrigado @DemetrioSQLDBA e @SQLInsane pela sugestão.

Frequentemente associamos o SQL Server às operações transacionais. Todas as informações são consistentes graças ao Transaction Log.

Entretanto, existe um serviço nativo do Windows chamado Microsoft Distributed Transaction Coordinator (MSDTC). Esse serviço executa as transações utilizando o protocolo chamado 2-Phase Commit. Qualquer recurso pode participar de uma transação distribuída. Por exemplo:

  • SQL Server (claro!)
  • Servidores Oracle
  • Filas IBM MQSeries
  • Componentes COM+

A arquitetura do MSDTC é composta por dois grandes componentes: Transaction Manager (TM) e Connection Manager (CM).

 

Transaction Manager

O componente do Transaction Manager (TM) é responsável por implementar o protocolo 2-Phase Commit. Embora ninguém fale desse jeito, gosto de pensar que as fases são:

  1. Persistência de dados – TM garante que as informações estão gravadas em disco
  2. Disponibilidade – O serviço do TM estará disponível para efetivar a modificação

Portanto, quando uma transação distribuída ocorre, todas as informações devem ser gravadas em seu respectivo storage em uma primeira fase. SQL Server armazena a informação no Transaction Log. Da mesma forma, imagino que o Oracle guarda os dados no Redo Log e o MQSeries armazena a mensagem em disco. Embora as informações estejam gravadas em log, elas ainda não estão disponíveis para a aplicação.

Durante a segunda fase, o MSDTC efetiva todas as transações.

  • Se qualquer recurso falhou na “fase 1 – persistência de dados” , então todas os recursos falham e fazem o ROLLBACK da informação. Parece estranho pensar que o SQL Server faz rollback do Transaction Log, mas é exatamente isso que ocorre no 2-Phase Commit.
  • Se *TODOS* os recursos conseguiram gravar os dados em disco, então é declarada a efetivação dos dados (COMMIT).

Observamos que o principal objetivo do MSDTC é coordenar os recursos transacionais (SQL, Oracle, MQ) usando o conceito de COMMIT ou ROLLBACK. Aqui existe a curiosa situação da transação IN-DOUBT:

  • Falhas durante a primeira fase causam o ROLLBACK
  • Falhas durante a segunda fase não afetam as transações, que já foram declaradas como COMMIT
  • Indisponibilidade de máquina na primeira fase tornam a transação IN-DOUBT – e a resolução é feita quando a máquina volta ao ar

 

Connection Manager

Em geral, existe um Transaction Manager (TM) por máquina. O serviço do MSDTC utiliza o protocolo RPC para se manter conectado com os demais TM.

RPC é um protocolo antigo e complexo. Todas as máquinas devem disponibilizar o serviço do RPC Locator na porta TCP 135, além de alocar dinamicamente uma porta TCP aleatória. Isso sempre causa dor de cabeça na hora de configurar o firewall. Já cansei de recomendar o artigo abaixo.

Configurando Microsoft coordenador de transações distribuídas (DTC) para trabalhar por meio de um firewall
https://support2.microsoft.com/kb/250367

Em geral, os problemas do MSDTC relacionados à conectividade podem ser facilmente diagnosticados com o DTCPing.

 

MSDTC não suportado?

Vou deixar como um desafio: você sabe por que o MSDTC não é suportado em um ambiente com Database Mirroring ou Availability Group? A explicação é similar ao motivo de não recomendarmos MSDTC local em instâncias clusterizadas.