Comprendiendo el error
El error “Communication with the underlying transaction manager has failed” ocurre cuando el servicio Microsoft Distributed Transaction Coordinator (MSDTC) en una máquina no puede comunicarse con el servicio MSDTC en otra máquina para coordinar una transacción distribuida.
El error completo y la excepción interna típicamente se ven así:
System.Transactions.TransactionManagerCommunicationException:
Communication with the underlying transaction manager has failed.
Inner Exception:
The MSDTC transaction manager was unable to pull the transaction from the
source transaction manager due to communication problems. Possible causes are:
a firewall is present and it doesn't have an exception for the MSDTC process,
the two machines cannot find each other by their NetBIOS names, or the support
for network transactions is not enabled for one of the two transaction managers.
(Exception from HRESULT: 0x8004D02B)
Esto ocurre comúnmente cuando:
- Una aplicación .NET usa
TransactionScopeentre múltiples instancias de SQL Server - Un procedimiento almacenado usa servidores vinculados con
BEGIN DISTRIBUTED TRANSACTION - Los servicios WCF usan enlaces transaccionales entre máquinas
Cuándo se activan las transacciones distribuidas
Es posible que no se dé cuenta de que su aplicación usa transacciones distribuidas. Se escalan automáticamente en estos escenarios:
// This creates a distributed transaction if conn1 and conn2 point to different servers
using (TransactionScope scope = new TransactionScope())
{
using (SqlConnection conn1 = new SqlConnection("Server=Server1;Database=DB1;..."))
using (SqlConnection conn2 = new SqlConnection("Server=Server2;Database=DB2;..."))
{
conn1.Open();
// Execute work on Server1
conn2.Open(); // This escalates to a distributed transaction
// Execute work on Server2
}
scope.Complete();
}
Incluso abrir dos conexiones al mismo servidor puede escalar a MSDTC en algunos casos (antes de .NET 4.0 con SQL Server 2008).
Solución paso a paso
Paso 1: Configurar los ajustes de seguridad de MSDTC
Esto debe hacerse en ambas máquinas involucradas en la transacción.
- Abra Servicios de componentes ejecutando
dcomcnfg - Navegue a: Servicios de componentes > Equipos > Mi PC > Coordinador de transacciones distribuidas > DTC local
- Haga clic derecho en DTC local y seleccione Propiedades
- Vaya a la pestaña Seguridad
- Configure los siguientes ajustes:
| Ajuste | Valor |
|---|---|
| Acceso DTC de red | Marcado |
| Permitir clientes remotos | Marcado |
| Permitir entrantes | Marcado |
| Permitir salientes | Marcado |
| Autenticación mutua requerida | Ver nota abajo |
| No se requiere autenticación | Seleccione esto si las máquinas NO están en el mismo dominio |
| Habilitar transacciones XA | Marcado (si usa XA) |
| Habilitar transacciones SNA LU 6.2 | Dejar desmarcado a menos que sea necesario |
Nota sobre autenticación: Si ambas máquinas están en el mismo dominio de Active Directory, use Autenticación mutua requerida. Si están en dominios o grupos de trabajo diferentes, use No se requiere autenticación.
- Haga clic en Aceptar y confirme que desea reiniciar el servicio MSDTC
Paso 2: Configurar el Firewall de Windows
La excepción interna menciona específicamente el firewall. En Windows 7, Windows Server 2008 y versiones posteriores, debe habilitar explícitamente la excepción de firewall para MSDTC, incluso si cree que ya lo ha hecho.
Usando el Firewall de Windows con seguridad avanzada
# Enable the predefined MSDTC firewall rules (do this on BOTH machines)
Enable-NetFirewallRule -DisplayGroup "Distributed Transaction Coordinator"
O manualmente a través de la interfaz gráfica:
- Abra Firewall de Windows con seguridad avanzada (
wf.msc) - Haga clic en Reglas de entrada
- Busque las reglas en el grupo Coordinador de transacciones distribuidas
- Habilite todas (clic derecho > Habilitar regla):
- Coordinador de transacciones distribuidas (RPC)
- Coordinador de transacciones distribuidas (RPC-EPMAP)
- Coordinador de transacciones distribuidas (TCP-In)
Repita para las reglas de salida también.
Configurar un puerto MSDTC fijo (recomendado para firewalls)
Por defecto, MSDTC usa puertos RPC dinámicos, lo que dificulta la configuración del firewall. Puede asignar un puerto fijo:
- Abra Servicios de componentes (
dcomcnfg) - Navegue a Mi PC > Coordinador de transacciones distribuidas > DTC local > Propiedades
- No hay interfaz gráfica para la configuración del puerto; use el registro:
Windows Registry Editor Version 5.00
[HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\MSDTC]
"ServerTcpPort"=dword:00001388
Esto configura MSDTC para usar el puerto TCP 5000 (0x1388). Luego cree una regla de firewall específica:
New-NetFirewallRule -DisplayName "MSDTC Fixed Port" -Direction Inbound -Protocol TCP -LocalPort 5000 -Action Allow
New-NetFirewallRule -DisplayName "MSDTC RPC" -Direction Inbound -Protocol TCP -LocalPort 135 -Action Allow
Después de cambiar el puerto, reinicie el servicio MSDTC:
Restart-Service -Name MSDTC
Paso 3: Verificar la resolución de nombres NetBIOS
Las dos máquinas deben poder resolver la otra por nombre NetBIOS, no solo por dirección IP o FQDN. MSDTC usa el nombre NetBIOS internamente.
Pruebe desde cada máquina:
:: From the client, test resolution of the server
ping SERVER1
nbtstat -a SERVER1
:: From the server, test resolution of the client
ping CLIENT1
nbtstat -a CLIENT1
Si la resolución de nombres falla, agregue entradas al archivo hosts en ambas máquinas:
# C:\Windows\System32\drivers\etc\hosts
10.0.1.10 SERVER1
10.0.1.20 CLIENT1
O mejor, asegúrese de que WINS o DNS con los registros apropiados esté configurado.
Paso 4: Verificar que el servicio MSDTC esté en ejecución
# Check MSDTC service status on both machines
Get-Service -Name MSDTC | Select-Object Name, Status, StartType
# Ensure it is set to start automatically
Set-Service -Name MSDTC -StartupType Automatic
Start-Service -Name MSDTC
Paso 5: Probar la comunicación de MSDTC
Use la herramienta DTCPing de Microsoft para probar la conectividad de MSDTC entre dos máquinas.
- Descargue DTCPing de Microsoft
- Ejecute
dtcping.exeen ambas máquinas simultáneamente - En cada máquina, ingrese el nombre NetBIOS de la otra máquina
- Haga clic en Ping: una prueba exitosa muestra “successfully completed” tanto para las pruebas RPC como de transacción
Alternativamente, pruebe desde PowerShell:
# Test RPC endpoint mapper connectivity
Test-NetConnection -ComputerName SERVER1 -Port 135
# Test the MSDTC fixed port (if configured)
Test-NetConnection -ComputerName SERVER1 -Port 5000
Transacciones distribuidas con SQL Server
Escenario: Consultas con servidor vinculado
Cuando SQL Server ejecuta una consulta a través de un servidor vinculado, MSDTC está involucrado:
-- This triggers a distributed transaction
BEGIN DISTRIBUTED TRANSACTION
INSERT INTO LocalDB.dbo.Orders (OrderID, CustomerName)
SELECT OrderID, CustomerName FROM [RemoteServer].RemoteDB.dbo.Orders
WHERE OrderDate > '2024-01-01';
COMMIT TRANSACTION
Asegúrese de que MSDTC esté configurado en ambas máquinas de SQL Server.
Escenario: .NET TransactionScope
using (var scope = new TransactionScope())
{
using (var conn = new SqlConnection(connectionString1))
{
conn.Open();
using (var cmd = conn.CreateCommand())
{
cmd.CommandText = "INSERT INTO Table1 (Col1) VALUES ('Value1')";
cmd.ExecuteNonQuery();
}
}
using (var conn = new SqlConnection(connectionString2))
{
conn.Open(); // Escalates to distributed transaction
using (var cmd = conn.CreateCommand())
{
cmd.CommandText = "INSERT INTO Table2 (Col1) VALUES ('Value2')";
cmd.ExecuteNonQuery();
}
}
scope.Complete();
}
Evitar transacciones distribuidas innecesarias
Si ambas conexiones apuntan a la misma instancia de SQL Server, puede evitar la escalación a MSDTC reutilizando una sola conexión:
using (var scope = new TransactionScope())
using (var conn = new SqlConnection(connectionString))
{
conn.Open();
using (var cmd1 = conn.CreateCommand())
{
cmd1.CommandText = "INSERT INTO DB1.dbo.Table1 (Col1) VALUES ('Value1')";
cmd1.ExecuteNonQuery();
}
using (var cmd2 = conn.CreateCommand())
{
cmd2.CommandText = "INSERT INTO DB2.dbo.Table2 (Col1) VALUES ('Value2')";
cmd2.ExecuteNonQuery();
}
scope.Complete();
}
Lista de verificación para solución de problemas
Recorra esta lista de verificación en ambas máquinas:
- El servicio MSDTC está en ejecución y configurado para inicio automático
- Los ajustes de seguridad de Servicios de componentes son correctos (Acceso DTC de red habilitado, Permitir entrantes/salientes)
- El Firewall de Windows tiene la excepción del Coordinador de transacciones distribuidas habilitada tanto para entrada como para salida
- La resolución de nombres NetBIOS funciona en ambas direcciones
- El mismo nivel de autenticación MSDTC en ambas máquinas (Autenticación mutua, Autenticación de llamador entrante, o Sin autenticación)
- El puerto RPC 135 es accesible entre las máquinas
- La prueba DTCPing tiene éxito en ambas direcciones
- El antivirus no está bloqueando el tráfico de MSDTC o RPC
- SQL Server tiene el acceso remoto habilitado (
sp_configure 'remote access', 1) - Entornos en clúster: Si SQL Server está en clúster, configure MSDTC como un recurso en clúster, no solo en los nodos individuales
Errores comunes
El Firewall de Windows “parece” abierto pero no lo está
En Windows 7 y Server 2008+, el firewall puede parecer que tiene las excepciones de MSDTC habilitadas, pero las reglas pueden estar aplicadas al perfil de red incorrecto (Dominio vs Privado vs Público). Verifique:
Get-NetFirewallRule -DisplayGroup "Distributed Transaction Coordinator" |
Select-Object Name, Enabled, Profile, Direction
Asegúrese de que las reglas estén habilitadas para el perfil correcto.
Diferentes instancias de MSDTC en un clúster
En un clúster de conmutación por error de Windows Server, cada instancia en clúster de SQL Server debe tener su propio recurso MSDTC. El MSDTC local en el nodo puede no ser el que está manejando las transacciones para la instancia de SQL en clúster.
Corrupción del archivo de registro de MSDTC
Si el archivo de registro de MSDTC está corrupto, el servicio puede iniciarse pero fallar al procesar transacciones:
:: Reset the MSDTC log
msdtc -resetlog
Resumen
El error “Communication with the underlying transaction manager has failed” es un problema de configuración de firewall y MSDTC. Para solucionarlo, abra Servicios de componentes en ambas máquinas y habilite el Acceso DTC de red con Permitir entrantes y Permitir salientes. Luego habilite la excepción del Coordinador de transacciones distribuidas en el Firewall de Windows en ambas máquinas. Verifique que las máquinas puedan resolver la otra por nombre NetBIOS, y use DTCPing para validar la comunicación MSDTC de extremo a extremo.