// Engineering Log

Standby cálido de la base de datos en otro hosting: replicación mínima de MySQL y PostgreSQL

Publicado el 02.11.2026 · Autor:

// Ruta rapida

Este articulo pertenece al tema Servidores e infraestructura.

Para un sitio pequeño o una tienda en línea, un clúster de bases de datos completamente tolerante a fallos es un exceso evidente: cuesta más que el propio negocio que debe proteger. Un objetivo razonable es más modesto: que, en caso de fallo del hosting principal, exista una copia actualizada de los datos en otro servidor que se pueda levantar manualmente con rapidez. Esto se llama copia en espera (warm standby): se actualiza en tiempo real, pero no acepta tráfico por sí misma ni realiza el cambio automáticamente — la decisión de conmutar la toma la persona.

A continuación — la configuración mínima de esa copia para MySQL/MariaDB y para PostgreSQL, sin herramientas adicionales de orquestación. Todo comprobado en dos máquinas reales (Debian 12 y Debian 13 — las versiones de las bases en los ejemplos son deliberadamente diferentes, eso también formó parte de la verificación).

MySQL y MariaDB: replicación incorporada

En MariaDB (y el MySQL compatible) la replicación está integrada en el propio servidor — no hace falta un paquete separado. El origen escribe todos los cambios en el registro binario (binlog), y la réplica se conecta al origen como cliente y reproduce esos cambios localmente.

En el origen hay que activar el registro y fijar un identificador de servidor único:

ini
# /etc/mysql/mariadb.conf.d/60-repl.cnf — en el servidor origen
[mysqld]
server_id = 1
log_bin = /var/lib/mysql/mariadb-bin
binlog_format = ROW
bind-address = 0.0.0.0

binlog_format = ROW significa que en el registro se escriben las filas modificadas en sí, no las sentencias SQL que las cambiaron — es más fiable, porque elimina discrepancias que pueden surgir al usar funciones no deterministas en las consultas (por ejemplo, NOW() o RAND(), que dan resultados distintos en el origen y en la réplica). A continuación — un usuario para replicación, accesible solo desde la dirección del segundo hosting:

sql
CREATE USER 'repl'@'<direccion_copia>' IDENTIFIED BY '<contraseña>';
GRANT REPLICATION SLAVE ON *.* TO 'repl'@'<direccion_copia>';

En la réplica — su propio identificador de servidor y la conexión por GTID (Global Transaction ID — número global de transacción, idéntico en origen y réplica; con él no hace falta buscar manualmente la posición en el registro, como exigía el método antiguo):

sql
CHANGE MASTER TO MASTER_HOST='<direccion_origen>',
                  MASTER_USER='repl', MASTER_PASSWORD='<contraseña>',
                  MASTER_USE_GTID=slave_pos,
                  MASTER_SSL=0;
START SLAVE;

La línea MASTER_SSL=0 no está por estética: al probar en MariaDB 11.8 la réplica sin este parámetro devolvía de inmediato el error SSL is required, but the server does not support it, aunque nadie hubiera solicitado cifrado explícitamente — en esa versión el cliente de replicación intenta usar TLS por defecto. Sin un certificado configurado en el origen es más sencillo desactivar el intento explícitamente que lidiar con certificados para una prueba; para un hosting real, si el tráfico de replicación va por Internet abierto (y no por una red privada del proveedor), conviene configurar TLS — de lo contrario la conexión entre origen y réplica se transmite en texto claro, incluyendo la contraseña usada al conectar, y todo el contenido de la base.

El estado de la réplica se comprueba con un comando:

SHOW SLAVE STATUS\G

Dos campos lo deciden todo: Slave_IO_Running: Yes indica que la réplica está recibiendo el binlog desde el origen, Slave_SQL_Running: Yes que está aplicando correctamente los cambios recibidos. Seconds_Behind_Master muestra el retraso en segundos — en la verificación fue cero: un registro insertado en el origen apareció en la réplica prácticamente al instante.

PostgreSQL: replicación en streaming

En PostgreSQL el principio es el mismo — el registro de transacciones (WAL, Write-Ahead Log) se transmite del servidor primario (primary) al de reserva (standby), sólo que la configuración es diferente: la réplica no se crea desde cero, sino como una copia binaria exacta del estado actual de la base, a la que luego se conecta el flujo de cambios.

Una condición importante que es fácil pasar por alto: la versión de PostgreSQL en ambos servidores debe coincidir — la replicación en streaming opera a nivel del formato interno de las páginas de datos, y puede variar entre versiones mayores. Si dos hostings ofrecen distintas versiones del SO con distintas versiones de PostgreSQL “de serie” (en la verificación fue así — Debian 12 y Debian 13 instalan por defecto PostgreSQL 15 y 17 respectivamente), en ambos servidores hay que instalar explícitamente la misma versión desde el repositorio oficial del proyecto (apt.postgresql.org), no desde el paquete del sistema.

En el servidor primario:

sql
ALTER SYSTEM SET wal_level = 'replica';
ALTER SYSTEM SET max_wal_senders = 5;
CREATE ROLE replicator WITH REPLICATION LOGIN PASSWORD '<contraseña>';
SELECT pg_create_physical_replication_slot('standby_shop');

El slot de replicación (replication slot) es una reserva nombrada de espacio en el registro en el lado del primario: mientras la réplica esté conectada a este slot, el primario no eliminará los archivos WAL, incluso si la réplica se queda atrasada o se desconecta temporalmente. Sin slot, el primario puede limpiar el WAL que la réplica necesita antes de que ésta lo haya copiado, y entonces habría que recrear la réplica desde cero.

En pg_hba.conf hace falta una línea que permita la replicación solo desde la dirección del segundo hosting:

host replication replicator <direccion_copia>/32 scram-sha-256

La propia réplica se crea con un único comando que se ejecuta en el futuro servidor de reserva — descarga una copia completa de la base desde el primario y configura de inmediato la conexión para continuar el streaming:

pg_basebackup -h <direccion_origen> -U replicator -D /var/lib/postgresql/17/main -P -R -X stream -S standby_shop

La opción -R crea el archivo standby.signal y escribe los parámetros de conexión al primario — no es necesario ponerlos a mano, el comando lo hace. Tras arrancar el servidor en la réplica, SELECT pg_is_in_recovery(); devuelve t (true) — el servidor está en modo de recuperación por streaming, es decir, es el standby y no el primario. En el primario el estado de la replicación se ve en pg_stat_replication: el campo replay_lag muestra el retraso en la aplicación — en la prueba fue de alrededor de un milisegundo.

Qué no protege esta configuración

Es importante entender los límites de la solución mínima, no solo lo que hace.

La replicación no es una copia de seguridad. Repite, ante todo, los errores, no los protege: un DELETE accidental sin condición, datos corruptos, la acción de un ransomware — todo eso la réplica lo reproducirá con gusto en segundos. Se necesitan copias de seguridad (dumps regulares almacenados aparte y con versionado temporal) en cualquier caso, independientemente de que exista replicación.

La conmutación es manual. Esta es una réplica en espera, no caliente automática: ante el fallo del servidor principal la aplicación no cambiará automáticamente a la réplica — hay que detener manualmente el modo de recuperación en PostgreSQL (pg_promote()) o reconvertir la réplica de MariaDB en servidor independiente, y cambiar manualmente la dirección a la que apunta la aplicación. La conmutación automática es otra tarea de clustering, y para una tienda pequeña su coste normalmente no compensa.

El puerto de la base está expuesto al exterior. En los ejemplos anteriores el firewall limita el acceso a los puertos 3306 y 5432 solo desde la dirección del segundo hosting, pero el puerto sigue escuchando en la interfaz externa. Para un esquema algo más seguro, en lugar de permitir directamente por IP es preferible un túnel (por ejemplo, WireGuard) entre los dos servidores — así el puerto de la base no es visible en Internet en absoluto, y el tráfico circula por un canal cifrado. Ese es el siguiente paso tras la configuración mínima; en este artículo no se desplegó por separado.

Conclusión

Tanto MySQL/MariaDB como PostgreSQL pueden mantener una copia actualizada en otro servidor con mecanismos que ya incluye la propia base, sin instalar software adicional. La configuración en ambos casos es cuestión de unos pocos parámetros y un comando para crear la réplica; la diferencia es que MariaDB se conecta a la base existente de inmediato, mientras que PostgreSQL la copia entera primero. Para un sitio o tienda pequeña cuya meta es “tener a dónde conmutar manualmente en caso de fallo”, y no “cero segundos de inactividad”, este es el mínimo razonable: más barato que un clúster, pero significativamente más fiable que no tener nada.

Fuentes: documentación de MariaDB (Standard Replication, GTID), documentación de PostgreSQL 17 (Streaming Replication, pg_basebackup).

// Tarea parecida

Si estas resolviendo algo parecido

Este articulo pertenece a uno de los temas principales de trabajo. Puedes seguir leyendo sobre el tema, ir a la pagina principal para entender a que me dedico o abrir directamente los servicios.

Tema del articulo

Servidores e infraestructura

VPS, Linux, stack web, migraciones, hosting, bases de datos y operacion base.

Tareas frecuentes de esta tema

  • Migrar un sitio o servicio a un nuevo servidor
  • Configurar Linux, Nginx, base de datos y copias de seguridad
  • Entender por que el sistema funciona de forma inestable

// Siguiente paso

Si necesitas ayuda con este tema y no solo otro articulo, es mejor ir directo a la pagina del servicio. La pagina principal y la seleccion de materiales quedan como rutas secundarias.

Abrir servicios

// Contact

¿Necesitas ayuda?

Escríbeme y te ayudaré a resolver el problema

Respondo en un día laborable (03:00-13:00 GMT)

O deje su solicitud aquí:

Confirme que no es un bot.

Escribir y recibir una respuesta rápida