
Por qué replicar
La replicación crea una o varias copias de la base de datos principal (primary/master) en otros servidores (replicas/standby). Los usos principales:
- Alta disponibilidad (HA): si el primary cae, una réplica asume el rol (failover).
- Distribución de carga de lectura: redirige
SELECTs a réplicas, dejando las escrituras al primary (pattern read-replicas). - Backup en caliente: haces
pg_basebackupomysqldumpdesde la réplica sin impactar al primary. - Geo-distribución: réplicas en regiones cercanas al usuario para latencia baja.
- Migraciones: replicación lógica para pasar datos a un nuevo servidor con versión distinta o esquema evolucionado.
PostgreSQL: streaming replication (física)
La replicación física envía el WAL (Write-Ahead Log) byte a byte al standby. El WAL es un log donde PostgreSQL registra cada cambio antes de aplicarlo. La réplica reproduce el WAL y mantiene una copia idéntica a nivel de archivo.
Configuración en el primary
En postgresql.conf:
wal_level = replica # o 'logical' si tambien quieres logical
max_wal_senders = 10
wal_keep_size = 1GB # WAL a conservar para replicas lentas (PG 13+)
archive_mode = on # opcional, para PITR
archive_command = 'cp %p /backup/wal/%f'
En pg_hba.conf permitir conexión de replicación:
host replication replicator 10.0.0.0/24 scram-sha-256
Crear usuario:
CREATE ROLE replicator WITH REPLICATION LOGIN PASSWORD 'secreto';
Bootstrap del standby
En el servidor replica:
# 1. Parar postgres si esta corriendo
systemctl stop postgresql
# 2. Limpiar data dir
rm -rf /var/lib/postgresql/data/*
# 3. Clonar desde el primary
pg_basebackup -h primary.host \
-U replicator \
-D /var/lib/postgresql/data \
-X stream \
-P \
-R # crea postgresql.auto.conf con los parametros de replica
# 4. Arrancar
systemctl start postgresql
El flag -R (PG 12+) genera automáticamente el archivo que activa el modo standby con la conexión al primary.
Verificar estado
-- En el primary
SELECT pid, usename, application_name, state, sync_state,
replay_lag, flush_lag, write_lag
FROM pg_stat_replication;
-- En la replica
SELECT pg_is_in_recovery(); -- t
SELECT pg_last_wal_receive_lsn(), pg_last_wal_replay_lsn();
Lag y sincronía
Por defecto la replicación es asíncrona: el primary no espera confirmación de la réplica para hacer COMMIT. Puedes configurar modos síncronos:
# primary: postgresql.conf
synchronous_commit = on # espera al menos al local WAL flush
synchronous_standby_names = 'replica1' # espera ACK de replica1 tambien
Con on, el primary espera a que al menos una réplica confirme antes de devolver COMMIT al cliente. Más seguro, pero más lento ante problemas de red.
Replication slots: evitar pérdida de WAL
Sin slots, si el standby está caído durante mucho tiempo, el primary puede recortar (WAL que el standby aún no replicó), y la replicación se rompe. Los replication slots indican al primary que debe retener ese WAL hasta que el standby lo consuma.
-- Crear slot en el primary
SELECT pg_create_physical_replication_slot('replica1_slot');
-- En la replica, configurar primary_slot_name
-- postgresql.auto.conf (generado por pg_basebackup -R + parametro)
primary_conninfo = 'host=primary.host user=replicator ...'
primary_slot_name = 'replica1_slot'
Cuidado: un slot olvidado sin consumidor bloquea el vacuum del WAL y puede llenar el disco. Monitoriza:
SELECT slot_name, active, restart_lsn,
pg_size_pretty(pg_wal_lsn_diff(pg_current_wal_lsn(), restart_lsn)) AS retained
FROM pg_replication_slots;
Logical replication (lógica)
La replicación lógica transmite cambios por tabla como eventos INSERT/UPDATE/DELETE. La réplica aplica esos cambios con SQL lógico, no copia archivos. Ventajas:
- Permite replicar subconjuntos de tablas.
- Funciona entre versiones distintas de PostgreSQL.
- Permite esquemas diferentes en origen y destino (p. ej. renames).
- No necesita que la réplica sea solo-lectura: puedes escribir en ella.
Usos: migración de versión mayor, ETL a data warehouse, CDC (Change Data Capture).
Configuración
En el primary:
wal_level = logical
-- Crear publication con las tablas a replicar
CREATE PUBLICATION mi_publicacion FOR TABLE pedidos, clientes;
-- O todas las tablas (PG 10+)
CREATE PUBLICATION todas_tablas FOR ALL TABLES;
En el destino:
-- Conectar al primary y suscribirse
CREATE SUBSCRIPTION mi_subscripcion
CONNECTION 'host=primary.host dbname=origen user=replicator password=...'
PUBLICATION mi_publicacion;
Automáticamente:
- Se hace un copy inicial de las tablas.
- Se sincronizan los cambios en streaming.
Monitorizar
-- En el primary
SELECT * FROM pg_stat_replication;
SELECT * FROM pg_publication_tables;
-- En el destino
SELECT * FROM pg_stat_subscription;
Failover: promocionar una réplica
Cuando el primary falla, promueves una réplica a primary:
-- En la replica (PG 12+)
SELECT pg_promote();
O con pg_ctl:
pg_ctl promote -D /var/lib/postgresql/data
La réplica deja el modo read-only y acepta escrituras. Las otras réplicas (si hay) apuntaban al antiguo primary y necesitan reconfigurarse para apuntar al nuevo.
En producción, nunca hagas failover manual. Usa herramientas:
- Patroni: orquestador popular con etcd/ZooKeeper/Consul.
- repmgr: de 2ndQuadrant.
- Stolon: similar a Patroni.
- PgBouncer + custom scripts: solución DIY ligera.
MySQL: replicación con binlog y GTID
MySQL usa el binary log (binlog) y desde 5.6+ los GTIDs (Global Transaction IDs) para identificar cada transacción de forma única.
Configuración del primary
my.cnf:
[mysqld]
server-id = 1
log-bin = mysql-bin
binlog_format = ROW # obligatorio para GTID
gtid_mode = ON
enforce_gtid_consistency = ON
Crear usuario:
CREATE USER 'repl'@'%' IDENTIFIED BY 'secreto';
GRANT REPLICATION SLAVE ON *.* TO 'repl'@'%';
Configuración del replica
my.cnf:
server-id = 2
log-bin = mysql-bin
gtid_mode = ON
enforce_gtid_consistency = ON
read_only = ON
Configurar y arrancar:
CHANGE REPLICATION SOURCE TO
SOURCE_HOST = 'primary.host',
SOURCE_USER = 'repl',
SOURCE_PASSWORD = 'secreto',
SOURCE_AUTO_POSITION = 1; -- usa GTID
START REPLICA;
SHOW REPLICA STATUS\G;
Los GTIDs permiten un failover más limpio: la nueva réplica sabe exactamente qué transacciones ha visto, sin depender de posiciones del binlog.
Semi-síncrono
Plugin que espera ACK de al menos una réplica antes de COMMIT en el primary. Bueno para evitar pérdida de datos ante crash del primary:
-- Primary
INSTALL PLUGIN rpl_semi_sync_master SONAME 'semisync_master.so';
SET GLOBAL rpl_semi_sync_master_enabled = 1;
-- Replica
INSTALL PLUGIN rpl_semi_sync_slave SONAME 'semisync_slave.so';
SET GLOBAL rpl_semi_sync_slave_enabled = 1;
Patrones de uso
Read replicas para escalado
Aplicación conecta a dos pools:
- Pool "escritor": apunta al primary. Para INSERT/UPDATE/DELETE.
- Pool "lector": round-robin sobre réplicas. Para SELECT.
Cuidado con el lag de replicación: si la aplicación inserta y lee inmediatamente, puede no ver su propia escritura desde la réplica. Patrón para resolverlo:
- Tras una escritura, leer siempre del primary durante N segundos.
- O usar
synchronous_commit = onpara que la réplica esté siempre al día (coste en latencia).
Migration dolgona con logical replication
Para migrar de PG 14 a PG 17 con downtime mínimo:
- Levanta el nuevo servidor PG 17.
- Crea publication en PG 14 y subscription en PG 17.
- Deja que sincronice semanas si hace falta.
- En una ventana corta: para la app, confirma lag = 0, cambia el DSN de la app al PG 17, arranca la app.
- Downtime real: minutos.
Checklist operativo
- [ ] Replication slots creados para todas las réplicas críticas.
- [ ] Monitorización de lag (
pg_stat_replication/SHOW REPLICA STATUS). - [ ] Alarmas si lag > umbral (ej. 30 segundos).
- [ ] WAL archiving configurado para PITR.
- [ ] Plan de failover documentado y probado.
- [ ]
synchronous_commitelegido según RPO aceptable. - [ ] Conexión cifrada (SSL) entre primary y réplicas.
- [ ] Contraseña del usuario de replicación en vault/secret manager.
Alan Sastre
Ingeniero de Software y formador, CEO en CertiDevs
Ingeniero de software especializado en Full Stack y en Inteligencia Artificial. Como CEO de CertiDevs, SQL es una de sus áreas de expertise. Con más de 15 años programando, 6K seguidores en LinkedIn y experiencia como formador, Alan se dedica a crear contenido educativo de calidad para desarrolladores de todos los niveles.
Más tutoriales de SQL
Explora más contenido relacionado con SQL y continúa aprendiendo con nuestros tutoriales gratuitos.
Aprendizajes de esta lección
Diferenciar streaming replication (fisica) de logical replication (replicacion por tablas). Configurar un replica streaming con pg_basebackup y recovery.conf / postgresql.auto.conf. Crear publications y subscriptions para replicacion logica. Comprender replication slots y su importancia para evitar perdida de WAL. Planificar failover y promocion de replica. Conocer GTID en MySQL y sus ventajas frente a posiciones de binlog.
Cursos que incluyen esta lección
Esta lección forma parte de los siguientes cursos estructurados con rutas de aprendizaje