Entendiendo la Replicación MySQL

La replicación MySQL permite que los datos de un servidor de base de datos (el primario, históricamente llamado “master”) se copien automáticamente a uno o más servidores adicionales (réplicas, históricamente llamadas “slaves”). Este mecanismo proporciona beneficios críticos: alta disponibilidad, escalado de lectura, distribución geográfica y descarga de respaldos.

A pesar de su madurez, la replicación MySQL no es algo que se configure y se olvide. Las derivas de configuración, los cambios de esquema, las discrepancias de hardware y las inestabilidades de red conspiran para producir fallos de replicación que pueden cascadear en inconsistencias de datos, errores de aplicación e incluso tiempo de inactividad.

Esta guía cubre los problemas más comunes de replicación MySQL, sus causas raíz y soluciones paso a paso tanto para topologías de replicación basadas en log binario tradicional como en GTID.

Requisitos Previos

  • Una configuración funcional de primario/réplica MySQL (MySQL 5.7+ o MySQL 8.0+).
  • Acceso shell a ambos servidores, primario y réplica.
  • Privilegios suficientes (SUPER o REPLICATION CLIENT) para ejecutar SHOW SLAVE STATUS.
  • Familiaridad con SQL básico y herramientas de línea de comandos Linux.
  • Opcional: Percona Toolkit instalado para diagnósticos avanzados.

Problemas Comunes de Replicación

Los siguientes cinco modos de falla representan la gran mayoría de los problemas de replicación MySQL:

  1. Retraso de Réplica (Seconds_Behind_Master > 0): La réplica no puede aplicar eventos del log binario tan rápido como el primario los produce.
  2. Errores de Clave Duplicada (Error 1062): Una fila que ya existe en la réplica está siendo insertada nuevamente por una transacción replicada.
  3. Errores de Fila Faltante (Error 1032): Un UPDATE o DELETE replicado hace referencia a una fila que no existe en la réplica.
  4. Corrupción del Relay Log: El archivo de relay log en la réplica se vuelve ilegible debido a errores de disco, fallos o apagados inadecuados.
  5. Divergencia GTID: En replicación basada en GTID, el conjunto de GTIDs ejecutados de la réplica ya no forma un superconjunto contiguo de lo que el primario espera.

Solución Paso a Paso

1. Evaluar el Estado Actual de Replicación

Siempre comience inspeccionando la salud de la réplica. En el servidor réplica, ejecute:

SHOW REPLICA STATUS\G

Para versiones de MySQL anteriores a 8.0.22, use SHOW SLAVE STATUS\G en su lugar.

Campos clave a inspeccionar:

CampoValor SaludableSignificado
Replica_IO_RunningYesEl hilo I/O está conectado al primario y leyendo logs binarios
Replica_SQL_RunningYesEl hilo SQL está aplicando eventos del relay log
Seconds_Behind_Source0Sin retraso de replicación
Last_Error(vacío)Sin errores encontrados

Si cualquiera de los hilos muestra No, enfóquese en los campos de error correspondientes: Last_IO_Error para problemas de I/O, Last_SQL_Error para fallos del lado de aplicación.

2. Corregir el Retraso de Réplica

El retraso de réplica significa que el hilo SQL no puede mantenerse al día con los eventos entrantes del log binario. Diagnostique con:

# Observar retraso en tiempo real
watch -n 1 "mysql -e 'SHOW REPLICA STATUS\G' | grep -E 'Seconds_Behind|Exec_Source_Log_Pos|Read_Source_Log_Pos'"

Causas comunes y soluciones:

A) Consultas lentas en la réplica:

-- Habilitar el log de consultas lentas en la réplica
SET GLOBAL slow_query_log = 1;
SET GLOBAL long_query_time = 1;
SET GLOBAL slow_query_log_file = '/var/log/mysql/replica-slow.log';

Identifique las consultas lentas y optimícelas con indexación adecuada.

B) Aplicación SQL de un solo hilo (MySQL 5.6 y anteriores):

Actualice a MySQL 5.7+ o 8.0+ y habilite la replicación multi-hilo:

-- MySQL 8.0+
STOP REPLICA;
SET GLOBAL replica_parallel_workers = 4;
SET GLOBAL replica_parallel_type = 'LOGICAL_CLOCK';
START REPLICA;

C) Cuello de botella de hardware: El I/O de disco de la réplica está saturado. Monitoree con iostat -x 1 y considere actualizar a SSDs o distribuir la carga de lectura entre múltiples réplicas.

3. Resolver Errores de Clave Duplicada (Error 1062)

Este error ocurre cuando la réplica ya tiene una fila que una transacción INSERT replicada está intentando crear. Causas típicas: escrituras manuales en la réplica o un respaldo restaurado que incluía transacciones que también llegarán por replicación.

Para replicación basada en log binario:

-- Saltar la transacción problemática
STOP SLAVE;
SET GLOBAL sql_slave_skip_counter = 1;
START SLAVE;

Para replicación basada en GTID:

-- Identificar el GTID fallido desde SHOW REPLICA STATUS -> Last_SQL_Error
STOP REPLICA;
SET GTID_NEXT = '3E11FA47-71CA-11E1-9E33-C80AA9429562:42';
BEGIN; COMMIT;  -- inyectar una transacción vacía
SET GTID_NEXT = 'AUTOMATIC';
START REPLICA;

Advertencia: Saltar transacciones puede introducir deriva de datos. Siempre valide con pt-table-checksum después.

4. Resolver Errores de Fila Faltante (Error 1032)

Cuando la réplica no puede encontrar la fila referenciada por un UPDATE o DELETE replicado:

-- Verificar qué tiene el primario
-- En el PRIMARIO:
SELECT * FROM mydb.mytable WHERE id = 12345;

-- En la RÉPLICA: comparar
SELECT * FROM mydb.mytable WHERE id = 12345;

Si la fila genuinamente debería existir en la réplica, insértela manualmente y luego reinicie la replicación. Si la fila fue eliminada intencionalmente en la réplica (señal de deriva de datos), salte la transacción como se muestra en la sección 3.

5. Recuperarse de Corrupción del Relay Log

Si el relay log está corrupto, el enfoque más seguro es volver a obtenerlo del primario:

STOP REPLICA;
RESET REPLICA;
-- Para replicación basada en GTID, la réplica automáticamente reanudará desde la posición correcta:
START REPLICA;

Para replicación basada en posición de log binario, necesita especificar la posición correcta:

STOP SLAVE;
RESET SLAVE;
CHANGE MASTER TO
  MASTER_LOG_FILE = 'mysql-bin.000042',
  MASTER_LOG_POS = 154;
START SLAVE;

6. Corregir Divergencia GTID

La divergencia GTID ocurre cuando la réplica tiene transacciones no presentes en el primario (frecuentemente por escrituras directas en la réplica). Diagnostique con:

-- En la RÉPLICA:
SELECT @@gtid_executed;
-- Comparar con el gtid_executed del primario

La solución depende de la gravedad:

  • Divergencia menor (pocas transacciones): Inyecte transacciones vacías en el primario para los GTIDs extra, o púrguelos de la réplica usando RESET MASTER.
  • Divergencia mayor: Reconstruya la réplica desde un respaldo fresco del primario usando mysqldump --single-transaction --source-data=2 o xtrabackup.

Prevención y Mejores Prácticas

  • Haga las réplicas de solo lectura: Configure read_only = 1 y super_read_only = 1 en todas las réplicas para prevenir escrituras accidentales.
  • Use replicación GTID: Simplifica enormemente el failover, re-apuntar réplicas y saltar transacciones comparado con el posicionamiento tradicional por log binario.
  • Monitoree el retraso de replicación continuamente: Use herramientas como Percona Monitoring and Management (PMM), Prometheus con mysqld_exporter, o la integración MySQL de Datadog.
  • Ejecute pt-table-checksum semanalmente: Detecte proactivamente la deriva de datos antes de que cause problemas a nivel de aplicación.
  • Automatice el failover cuidadosamente: Herramientas como Orchestrator, MHA, o MySQL InnoDB Cluster / Group Replication proporcionan failover automatizado, pero pruébelas exhaustivamente en staging antes de confiar en ellas en producción.

Resumen

  • Los fallos de replicación MySQL típicamente se reducen a retraso, errores de filas duplicadas/faltantes, corrupción del relay log o divergencia GTID.
  • Siempre inicie el diagnóstico con SHOW REPLICA STATUS e inspeccione los campos Replica_IO_Running, Replica_SQL_Running y Last_Error.
  • Use sql_slave_skip_counter o transacciones GTID vacías para pasar errores individuales, pero siempre valide la consistencia de datos después.
  • Prevenga problemas imponiendo read_only en réplicas, usando replicación GTID, habilitando configuraciones crash-safe y monitoreando continuamente.

Artículos Relacionados