🎨 Sysprovider Code
Sysprovider LogoWiki
🇪🇸Hosting español para ecommerce

Migración de servidores MySQL a Percona XtraDB Cluster sin downtime

Actualizado el 19 de enero de 2026

Introducción: El Desafío de la Alta Disponibilidad en MySQL

En entornos de producción críticos, la migración de un servidor MySQL mononodo a un clúster de alta disponibilidad como Percona XtraDB Cluster (PXC) debe realizarse sin interrumpir el servicio. El downtime se traduce en pérdida de ingresos, degradación de la experiencia de usuario y, en muchos casos, incumplimiento de SLAs. PXC, basado en Galera, ofrece replicación síncrona multi-maestro, pero su implementación requiere un proceso meticuloso para evitar split-brain, inconsistencias de datos o bloqueos prolongados.

Este artículo detalla una estrategia de migración cero downtime desde un servidor MySQL/MariaDB standalone hacia un clúster PXC de 3 nodos. Asumimos que el servidor origen es MySQL 8.0 (o MariaDB 10.x con wsrep) y que el destino serán nodos con Percona Server 8.0 y Galera. No cubrimos la migración desde versiones obsoletas (MySQL 5.6/5.7) sin antes realizar una actualización menor.

Arquitectura Objetivo y Prerrequisitos

Componentes del Clúster PXC

NodoRol InicialIP EjemploFunción Final
Nodo 0 (Origen)MySQL Standalone192.168.1.10Se convertirá en miembro del clúster
Nodo 1Nuevo PXC192.168.1.11Miembro del clúster
Nodo 2Nuevo PXC192.168.1.12Miembro del clúster

Prerrequisitos Técnicos

  1. Versiones compatibles: Percona XtraDB Cluster 8.0 requiere Percona Server 8.0.x. Verificar compatibilidad con wsrep API.
  2. Red de baja latencia: Galera requiere latencia < 10ms entre nodos (ideal < 1ms). Usar VLAN dedicada o interfaces privadas.
  3. Almacenamiento homogéneo: Todos los nodos deben usar el mismo motor de almacenamiento (InnoDB). No se permite MyISAM en tablas del clúster.
  4. Configuración de tiempo: NTP sincronizado en todos los nodos. Galera usa timestamps para ordenar transacciones.
  5. Espacio en disco: Almacenamiento adicional para el snapshot inicial (al menos 1.5x el tamaño actual de la base de datos).

⚠️ Advertencia crítica: No intentes esta migración en producción sin un entorno de staging idéntico. La replicación síncrona de Galera impone restricciones (ej: tablas sin clave primaria, transacciones largas) que pueden causar fallos en el clúster.

Fase 1: Preparación del Servidor Origen

1.1 Configuración de Binlog y GTID

Galera utiliza transacciones atómicas globales (GTID) para identificar eventos. Debemos habilitar el log binario en el nodo origen si no está activo:

# En /etc/my.cnf (o /etc/mysql/my.cnf)
[mysqld]
server_id=1
log_bin=/var/log/mysql/mysql-bin.log
binlog_format=ROW
expire_logs_days=7
gtid_mode=ON
enforce_gtid_consistency=ON

¿Por qué ROW?: Galera requiere replicación basada en filas (ROW) para garantizar consistencia. El formato STATEMENT puede causar divergencias debido a funciones no deterministas (NOW(), UUID()).

1.2 Ajuste de Tablas para Galera

Galera impone restricciones estrictas. Identifica y corrige problemas antes de la migración:

-- Encontrar tablas sin clave primaria (PXC requiere PK)

SELECT t.table_schema, t.table_name, t.engine

FROM information_schema.tables t

WHERE t.table_schema NOT IN ('mysql', 'performance_schema', 'sys')
  AND (SELECT COUNT(*) FROM information_schema.columns c 
       WHERE c.table_schema = t.table_schema 
         AND c.table_name = t.table_name 
         AND c.column_key IN ('PRI', 'UNI')) = 0;

-- Verificar tablas MyISAM (deben convertirse a InnoDB)

SELECT table_schema, table_name, engine 

FROM information_schema.tables 

WHERE engine = 'MyISAM' 
  AND table_schema NOT IN ('mysql', 'performance_schema', 'sys');

Para convertir tablas MyISAM a InnoDB (sin downtime usando pt-online-schema-change):

# Instalar Percona Toolkit si no está presente
apt install percona-toolkit

# Convertir tabla sin bloquear (usa triggers)
pt-online-schema-change --alter "ENGINE=InnoDB" D=db_ventas,t=facturas \
  --execute --no-drop-old-table --chunk-size=1000

1.3 Habilitar Modo wsrep en el Nodo Origen

Aunque el nodo origen no será parte del clúster inicialmente, debemos cargar el plugin wsrep para facilitar la transición:

# Instalar paquete wsrep (para MySQL nativo se necesita recompilar)
# En Percona Server ya viene incluido

INSTALL PLUGIN wsrep SONAME 'wsrep_info.so';

# Verificar que el plugin esté activo

SHOW PLUGINS LIKE 'wsrep%';

Fase 2: Configuración de los Nuevos Nodos PXC

2.1 Instalación de Percona XtraDB Cluster

En cada nodo nuevo (Nodo 1 y Nodo 2):

# Agregar repositorio Percona
wget https://repo.percona.com/apt/percona-release_latest.generic_all.deb
dpkg -i percona-release_latest.generic_all.deb
apt update

# Instalar PXC (versión 8.0)
apt install percona-xtradb-cluster-server-8.0 percona-xtrabackup-80

2.2 Configuración del Clúster (my.cnf)

Ejemplo de configuración para el Nodo 1:

[mysqld]
# Identidad del nodo
server_id=1
wsrep_node_name=pxc-node-1
wsrep_node_address=192.168.1.11

# Configuración del clúster
wsrep_cluster_name=pxc-prod-cluster
wsrep_cluster_address=gcomm://192.168.1.10,192.168.1.11,192.168.1.12

# Proveedor Galera
wsrep_provider=/usr/lib/libgalera_smm.so
wsrep_provider_options="gcache.size=1G; gcache.recover=yes"

# Configuración de replicación
binlog_format=ROW
default_storage_engine=InnoDB
wsrep_slave_threads=8
wsrep_log_conflicts=ON

# Seguridad
wsrep_sst_method=xtrabackup-v2
wsrep_sst_auth=sst_user:strong_password
pxc_encrypt_cluster_traffic=ON

# Ajustes de rendimiento
innodb_autoinc_lock_mode=2
innodb_flush_log_at_trx_commit=1
innodb_buffer_pool_size=8G  # Ajustar según RAM disponible

Explicación de parámetros clave:

  • wsrep_sst_method=xtrabackup-v2: Método de transferencia de snapshot inicial. Usa Percona XtraBackup para copia consistente sin bloqueo.
  • wsrep_slave_threads: Número de hilos para aplicar writesets (recomendado: 2-4x número de cores).
  • pxc_encrypt_cluster_traffic=ON: Cifra tráfico entre nodos (requiere certificados SSL).
  • innodb_autoinc_lock_mode=2: Permite inserción concurrente en tablas con AUTO_INCREMENT (esencial para Galera).

2.3 Generación de Certificados SSL (Opcional pero Recomendado)

# En el nodo que iniciará el clúster
openssl req -new -x509 -days 365 -nodes -text -out server-cert.pem \
  -keyout server-key.pem -subj "/CN=pxc-cluster"

# Copiar a todos los nodos
scp server-cert.pem server-key.pem ca-cert.pem nodoX:/etc/mysql/ssl/

# En my.cnf agregar:
[mysqld]
ssl-ca=/etc/mysql/ssl/ca-cert.pem
ssl-cert=/etc/mysql/ssl/server-cert.pem
ssl-key=/etc/mysql/ssl/server-key.pem

Fase 3: Estrategia de Migración Cero Downtime

Utilizaremos una técnica de replicación asíncrona previa (MySQL Replication tradicional) para sincronizar datos antes de unir el nodo origen al clúster. Luego, haremos un cambio rápido de DNS/Load Balancer.

3.1 Creación de Usuario de Replicación en Origen


CREATE USER 'repl'@'192.168.1.%' IDENTIFIED BY 'secure_password';

GRANT REPLICATION SLAVE, REPLICATION CLIENT ON *.* TO 'repl'@'192.168.1.%';

FLUSH PRIVILEGES;

3.2 Toma de Snapshot Inicial con XtraBackup

En el nodo origen (sin detener MySQL):

# Realizar backup completo con streaming
xtrabackup --backup --stream=xbstream --target-dir=/tmp/backup \
  --user=root --password=root_password \
  | ssh nodo1 "xbstream -x -C /var/lib/mysql"

# En nodo1, preparar el backup (aplicar logs)
xtrabackup --prepare --target-dir=/var/lib/mysql

¿Por qué XtraBackup y no mysqldump?: XtraBackup permite copias consistentes sin bloqueo de tablas. mysqldump requeriría un lock global (FLUSH TABLES WITH READ LOCK) que causa downtime.

3.3 Configuración de Replicación Asíncrona

En el Nodo 1, configurar como esclavo del origen:


CHANGE MASTER TO
  MASTER_HOST='192.168.1.10',
  MASTER_USER='repl',
  MASTER_PASSWORD='secure_password',
  MASTER_LOG_FILE='mysql-bin.000012',
  MASTER_LOG_POS=456789,
  MASTER_SSL=1;  -- Si usas SSL

START SLAVE;

-- Verificar estado

SHOW SLAVE STATUS\G

Repetir para el Nodo 2 (puede iniciar desde el mismo binlog).

3.4 Monitoreo del Lag de Replicación

# Script simple para monitorear
watch -n 1 "mysql -e 'SHOW SLAVE STATUS\G' | grep -E 'Seconds_Behind_Master|Slave_IO_Running|Slave_SQL_Running'"

Esperar hasta que Seconds_Behind_Master sea 0 durante al menos 5 minutos consecutivos.

Fase 4: Unión del Nodo Origen al Clúster

4.1 Preparación del Nodo Origen para Galera

Detener MySQL en el nodo origen y modificar su configuración:

systemctl stop mysql

# Agregar configuración wsrep similar a los nodos nuevos
# Cambiar wsrep_cluster_address a gcomm://192.168.1.11,192.168.1.12
# (el origen se unirá como nuevo miembro)

4.2 Bootstrap del Clúster (Primera Inicialización)

Elegir un nodo (preferiblemente el que tiene los datos más actualizados, Nodo 1) para iniciar el clúster:

# En Nodo 1, iniciar con bootstrap (solo primera vez)
systemctl start mysql@bootstrap.service
# O manualmente:
mysqld --wsrep-new-cluster --user=mysql &

Verificar que el clúster tenga un solo miembro:


SHOW STATUS LIKE 'wsrep_cluster_size';
-- Debe mostrar 1

4.3 Inicio de Nodos Restantes

En Nodo 2 y luego en Nodo Origen:

systemctl start mysql

Cada nodo se unirá automáticamente al clúster. Verificar:


SHOW STATUS LIKE 'wsrep_local_state_comment';
-- Debe mostrar 'Synced' en todos

4.4 Verificación de Consistencia de Datos

Ejecutar en cualquier nodo:

-- Comparar número de filas en tablas críticas

SELECT COUNT(*) FROM db_ventas.facturas;

-- Verificar estado del clúster

SHOW STATUS LIKE 'wsrep_%';

Fase 5: Conmutación de Tráfico (Cutover)

5.1 Configuración de ProxySQL o HAProxy

Implementar un balanceador de capa 4/7 para distribuir tráfico sin downtime:

# Ejemplo HAProxy /etc/haproxy/haproxy.cfg
frontend mysql_front
    bind *:3306
    default_backend mysql_back

backend mysql_back
    balance leastconn
    option mysql-check user haproxy_check
    server pxc1 192.168.1.11:3306 check inter 2000
    server pxc2 192.168.1.12:3306 check inter 2000
    server pxc3 192.168.1.10:3306 check inter 2000

5.2 Redirección Gradual (DNS TTL)

Para aplicaciones que usan DNS:

  1. Reducir TTL del registro A a 60 segundos (24h antes).
  2. Cambiar registro A para apuntar al VIP del balanceador.
  3. Esperar propagación (mínimo 2 TTL).
  4. Verificar que todas las conexiones nuevas pasen por PXC.

5.3 Verificación de Aplicaciones

# Probar conexión desde aplicación
mysql -h balanceador_vip -u app_user -p -e "SELECT 1"

# Verificar que no haya consultas en estado 'killed' o 'locked'

SHOW PROCESSLIST;

Fase 6: Post-Migración y Ajustes

6.1 Monitoreo de Conflictos

Galera puede tener conflictos de escritura simultánea. Monitorear:


SHOW STATUS LIKE 'wsrep_local_bf_aborts';

SHOW STATUS LIKE 'wsrep_local_cert_failures';

Si los valores son > 0, revisar lógica de aplicación (evitar transacciones largas o escrituras concurrentes en misma fila).

6.2 Ajuste de gcache

El tamaño de gcache (caché de writesets) debe ser suficiente para que nodos caídos se recuperen sin SST:


SHOW STATUS LIKE 'wsrep_gcache_pool_size';
-- Ajustar en my.cnf: wsrep_provider_options="gcache.size=2G"

6.3 Configuración de Donor Select

Para SST (State Snapshot Transfer), elegir el método de donante:

wsrep_sst_donor=pxc-node-1,pxc-node-2

Esto evita que el nodo origen (con menos recursos) sea donante.

Solución de Problemas Comunes

Escenario 1: Nodo no se une al clúster

# Verificar logs
tail -100 /var/log/mysql/error.log | grep -i "wsrep"

# Causas comunes:
# - Firewall bloqueando puertos 3306, 4444, 4567, 4568
# - Versiones incompatibles de wsrep
# - Diferencia en parámetros wsrep_provider_options

Escenario 2: SST falla por falta de espacio

# Aumentar espacio temporal
mkdir /tmp/sst && chown mysql:mysql /tmp/sst
# En my.cnf:
[xtrabackup]
tmpdir=/tmp/sst

Escenario 3: Split-brain por pérdida de quorum

Si 2 de 3 nodos caen, el nodo restante se vuelve no primario (no acepta escrituras). Solución:

# En el nodo superviviente (solo si estás seguro de que es el único con datos)
systemctl stop mysql
mysqld --wsrep-recover
# Luego iniciar con bootstrap
mysqld --wsrep-new-cluster &

Conclusión y Mejores Prácticas

La migración exitosa a PXC sin downtime depende de:

  1. Preparación exhaustiva: Tablas sin PK, MyISAM, transacciones largas.
  2. Uso de herramientas adecuadas: XtraBackup para SST, ProxySQL para balanceo.
  3. Monitoreo continuo: wsrep_local_state_comment, `wsrep_cluster

¿Necesitas ayuda?Son dos de nuestros técnicos, Agustín y Mikel, y están disponibles para resolver cualquier problema.

Hablar con ellos ahora
Agustín y Mikel