TL;DR — Resumen Rápido
Guia completa de replicacion MySQL master-slave para alta disponibilidad: binary logs, configuracion de slaves, monitoreo de lag, failover y ProxySQL.
La replicacion de MySQL permite que un servidor (el master) transmita cada cambio de datos a uno o mas servidores replica (slaves) en tiempo casi real. El resultado es una arquitectura de alta disponibilidad donde el trafico de lectura se distribuye entre multiples nodos, los respaldos se pueden tomar desde un slave sin afectar al master, y un slave puede promoverse a master en minutos si el servidor primario falla. Esta guia cubre la configuracion completa de replicacion master-slave en MySQL 8.0: desde la configuracion de binary logs y la sincronizacion inicial de datos hasta el monitoreo de lag, la recuperacion de replicacion rota, los procedimientos de failover y la separacion de lectura/escritura con ProxySQL.
Arquitectura de Replicacion
La replicacion de MySQL funciona mediante tres componentes que trabajan en conjunto:
- Binary log (binlog) — el master registra cada transaccion confirmada en un archivo de log secuencial. Existen tres formatos:
STATEMENT(registra el texto SQL),ROW(registra los valores antes/despues de las filas modificadas) yMIXED(usa STATEMENT por defecto y cambia a ROW para funciones no deterministas). Usa siempreROWen produccion. - IO thread — un hilo en el slave se conecta al master, lee los nuevos eventos del binary log y los escribe en el relay log local.
- SQL thread — un segundo hilo en el slave lee el relay log y reproduce los eventos contra la base de datos local, manteniendo los datos sincronizados.
Modos de Replicacion
| Modo | Como Funciona | Cuando Usarlo |
|---|---|---|
| Asincrono (defecto) | El master no espera ACK del slave | HA general, escalado de lecturas |
| Semi-sincrono | El master espera que al menos un slave escriba el relay log | Datos financieros, menor riesgo de perdida |
| Group Replication | Multi-master con protocolo de consenso (Paxos) | Activo-activo, failover automatico |
Prerrequisitos
- Dos servidores Linux con MySQL 8.0 o 8.4 (Ubuntu 22.04+ o RHEL 9+)
- Acceso root o sudo en ambos servidores
- Conectividad de red entre master y slave (puerto 3306 abierto)
- server-id del master y del slave deben ser enteros unicos en toda la topologia
Paso 1: Configurar el Servidor Master
Edita la configuracion de MySQL en el master:
sudo nano /etc/mysql/mysql.conf.d/mysqld.cnf
Agrega o modifica estas opciones en la seccion [mysqld]:
[mysqld]
# ID unico para este servidor — debe ser diferente en cada nodo
server-id = 1
# Habilita el binary log — obligatorio para replicacion
log-bin = /var/log/mysql/mysql-bin
binlog-format = ROW
# Conserva 7 dias de binary logs
expire_logs_days = 7
# Sincroniza el binlog a disco en cada commit — evita perdida de datos
sync_binlog = 1
# Replicacion basada en GTID (recomendada para MySQL 8.0+)
gtid_mode = ON
enforce_gtid_consistency = ON
Aplica la configuracion:
sudo systemctl restart mysql
Verifica que el binary log este activo:
SHOW VARIABLES LIKE 'log_bin';
-- log_bin | ON
SHOW MASTER STATUS\G
-- File: mysql-bin.000003
-- Position: 1573
Paso 2: Crear el Usuario de Replicacion
En el master, crea un usuario dedicado con solo los permisos necesarios para replicacion:
CREATE USER 'repl'@'192.168.1.102' IDENTIFIED BY 'ReplStr0ng!Pass';
GRANT REPLICATION SLAVE ON *.* TO 'repl'@'192.168.1.102';
FLUSH PRIVILEGES;
Reemplaza 192.168.1.102 con la IP real del slave. Nunca uses % (cualquier host) para usuarios de replicacion — restringe por IP por seguridad.
Paso 3: Tomar un Snapshot Consistente
Necesitas un snapshot consistente en un punto del tiempo del master para inicializar el slave. El flag --master-data registra automaticamente la posicion del binary log dentro del archivo de volcado.
# Opcion A: mysqldump (adecuado para bases de datos menores a ~50 GB)
mysqldump -u root -p \
--all-databases \
--master-data=2 \
--single-transaction \
--flush-logs \
--routines \
--triggers \
> /tmp/master_dump.sql
# Opcion B: Percona XtraBackup (recomendado para bases grandes, sin bloqueo de tablas)
xtrabackup --backup --user=root --password=mipass \
--target-dir=/tmp/xtrabackup/
xtrabackup --prepare --target-dir=/tmp/xtrabackup/
Transfiere el volcado al slave:
scp /tmp/master_dump.sql usuario@192.168.1.102:/tmp/
Paso 4: Configurar el Servidor Slave
En el slave, edita mysqld.cnf:
[mysqld]
# Debe ser diferente al master y a todos los demas slaves
server-id = 2
# Ubicacion del relay log
relay-log = /var/log/mysql/mysql-relay-bin
# Evita escrituras accidentales en el slave
read_only = 1
super_read_only = 1
# Necesario si este slave sera a su vez un master (replicacion en cadena)
log_slave_updates = 1
# Coincide con la configuracion GTID del master
gtid_mode = ON
enforce_gtid_consistency = ON
sudo systemctl restart mysql
Paso 5: Importar el Snapshot e Iniciar la Replicacion
Restaura el volcado del master en el slave:
mysql -u root -p < /tmp/master_dump.sql
Configura el slave para conectarse al master. Con modo GTID (recomendado):
CHANGE MASTER TO
MASTER_HOST = '192.168.1.101',
MASTER_USER = 'repl',
MASTER_PASSWORD = 'ReplStr0ng!Pass',
MASTER_AUTO_POSITION = 1;
Sin GTID (basado en posicion tradicional), busca la posicion en el comentario del volcado:
grep "MASTER_LOG_FILE\|MASTER_LOG_POS" /tmp/master_dump.sql | head -5
# -- CHANGE MASTER TO MASTER_LOG_FILE='mysql-bin.000003', MASTER_LOG_POS=1573;
CHANGE MASTER TO
MASTER_HOST = '192.168.1.101',
MASTER_USER = 'repl',
MASTER_PASSWORD = 'ReplStr0ng!Pass',
MASTER_LOG_FILE = 'mysql-bin.000003',
MASTER_LOG_POS = 1573;
Inicia la replicacion:
START SLAVE;
Paso 6: Monitorear la Salud de la Replicacion
SHOW SLAVE STATUS\G
Campos clave a verificar:
Slave_IO_Running: Yes -- hilo IO conectado y funcionando
Slave_SQL_Running: Yes -- hilo SQL reproduciendo eventos
Seconds_Behind_Master: 0 -- slave completamente al dia
Last_IO_Error: (vacio) -- sin errores de conexion
Last_SQL_Error: (vacio) -- sin errores de reproduccion
Para monitoreo continuo mediante performance_schema (MySQL 8.0+):
SELECT
CHANNEL_NAME,
SERVICE_STATE,
LAST_ERROR_MESSAGE,
LAST_HEARTBEAT_TIMESTAMP
FROM performance_schema.replication_connection_status;
Manejo del Lag de Replicacion
El lag de replicacion (Seconds_Behind_Master creciendo) es comun bajo cargas de escritura intensas:
| Causa | Solucion |
|---|---|
| Hilo SQL de un solo subproceso | Habilita workers de replicacion paralela |
| Consultas lentas en el slave | Identifica con SHOW PROCESSLIST; optimiza |
| Cuello de botella de I/O en el slave | Mueve los relay logs a almacenamiento mas rapido |
| Transacciones masivas | Divide en lotes mas pequenos en el master |
| Latencia de red | Coloca master y slaves en el mismo datacenter |
Habilitar replicacion paralela (MySQL 8.0):
STOP SLAVE SQL_THREAD;
SET GLOBAL slave_parallel_workers = 4;
SET GLOBAL slave_parallel_type = 'LOGICAL_CLOCK';
START SLAVE SQL_THREAD;
Reparar la Replicacion Rota
Cuando Slave_SQL_Running: No aparece en SHOW SLAVE STATUS:
Saltar una Sola Transaccion con Error
STOP SLAVE;
SET GLOBAL sql_slave_skip_counter = 1;
START SLAVE;
SHOW SLAVE STATUS\G
Saltar por GTID (Mas Seguro con Modo GTID)
STOP SLAVE;
-- Reemplaza con el GTID del mensaje Last_SQL_Error
SET GTID_NEXT = 'a1b2c3d4-1111-2222-3333-444444444444:1234';
BEGIN; COMMIT;
SET GTID_NEXT = 'AUTOMATIC';
START SLAVE;
Resincronizacion Completa desde el Master
STOP SLAVE;
RESET SLAVE ALL;
-- Toma el snapshot nuevamente desde el Paso 3 y reconfigura
Failover: Promover un Slave a Master
Cuando el master falla y necesitas promover un slave:
-- En el slave a promover:
SHOW SLAVE STATUS\G
-- Seconds_Behind_Master: 0
STOP SLAVE;
RESET SLAVE ALL;
-- Deshabilita modo de solo lectura — este servidor es ahora el master
SET GLOBAL read_only = 0;
SET GLOBAL super_read_only = 0;
Actualiza las cadenas de conexion de la aplicacion a la nueva IP del master y reconfigura los slaves restantes:
-- En los slaves restantes:
STOP SLAVE;
CHANGE MASTER TO
MASTER_HOST = '192.168.1.102',
MASTER_AUTO_POSITION = 1;
START SLAVE;
Paso 7: ProxySQL para Separacion Lectura/Escritura
ProxySQL se situa entre la aplicacion y MySQL, enrutando escrituras al master y lecturas a los slaves de forma transparente.
# Instalar ProxySQL (Ubuntu)
wget -O - 'https://repo.proxysql.com/ProxySQL/repo_pub_key' | sudo apt-key add -
echo "deb https://repo.proxysql.com/ProxySQL/proxysql-2.x/$(lsb_release -sc)/ ./" \
| sudo tee /etc/apt/sources.list.d/proxysql.list
sudo apt update && sudo apt install proxysql
sudo systemctl enable --now proxysql
Configura mediante la interfaz admin de ProxySQL (puerto 6032):
-- Agregar servidores: hostgroup 0 = escritura (master), hostgroup 1 = lectura (slave)
INSERT INTO mysql_servers (hostgroup_id, hostname, port) VALUES
(0, '192.168.1.101', 3306),
(1, '192.168.1.102', 3306);
-- Agregar usuario de la aplicacion
INSERT INTO mysql_users (username, password, default_hostgroup) VALUES
('appuser', 'AppPass123!', 0);
-- Enrutar consultas SELECT al hostgroup de lectura
INSERT INTO mysql_query_rules (rule_id, active, match_digest, destination_hostgroup, apply) VALUES
(1, 1, '^SELECT.*', 1, 1);
-- Aplicar y persistir cambios
LOAD MYSQL SERVERS TO RUNTIME; SAVE MYSQL SERVERS TO DISK;
LOAD MYSQL USERS TO RUNTIME; SAVE MYSQL USERS TO DISK;
LOAD MYSQL QUERY RULES TO RUNTIME; SAVE MYSQL QUERY RULES TO DISK;
La aplicacion se conecta a ProxySQL en el puerto 6033 y todo el enrutamiento se gestiona de forma transparente.
Comparacion: Replicacion MySQL vs Alternativas
| Solucion | Arquitectura | Failover | Escalado de Escrituras | Complejidad |
|---|---|---|---|---|
| Replicacion MySQL | Master + slaves | Manual o MHA | No (master unico) | Baja |
| MySQL Group Replication | Multi-master Paxos | Automatico | Limitado | Media |
| Galera Cluster (MariaDB) | Multi-master sincrono | Automatico | Si | Media |
| Vitess | MySQL con sharding | Automatico | Si (sharding) | Alta |
| PlanetScale | Vitess administrado | Administrado | Si | Baja (administrado) |
| PostgreSQL Streaming | Primario + standbys | Patroni/manual | No | Baja-Media |
La replicacion asincrona de MySQL es el punto de partida de menor complejidad. Migra a Group Replication o Galera cuando necesites failover automatico.
Casos Especiales y Advertencias
- server-id debe ser globalmente unico en todos los nodos — dos nodos con el mismo ID corrompen silenciosamente la replicacion
read_only=1no bloquea a usuarios SUPER — usasuper_read_only=1para bloquear completamente el slave- Las transacciones grandes bloquean el hilo IO — usa
pt-online-schema-changepara operaciones DDL grandes - Diferencias de zona horaria causan errores de replicacion — establece
default-time-zone='+00:00'en todos los nodos
Resumen
- La replicacion MySQL usa binary logs, hilos IO y hilos SQL para mantener los slaves sincronizados
- Usa
binlog-format=ROW,sync_binlog=1y modo GTID (gtid_mode=ON) en produccion - Monitorea
Slave_IO_Running,Slave_SQL_RunningySeconds_Behind_Mastercontinuamente - Habilita workers de replicacion paralela para reducir el lag bajo cargas de escritura intensas
- Usa
RESET SLAVE ALLpara una reconfiguracion limpia en lugar de intentar parchear un estado roto - ProxySQL enruta transparentemente las lecturas a los slaves y las escrituras al master