Cómo planificar y ejecutar un rollback seguro al actualizar la versión major de PostgreSQL (12→14) en producción con réplica de lectura — guía práctica
Por Kevin Marcondes · Publicado el · 10 min de lectura
Guía: cómo planificar y ejecutar un rollback seguro al actualizar PostgreSQL 12→14 en producción con réplica de lectura. Verás prerequisitos, cuándo usar pg_upgrade o replicación lógica, cómo realizar el cutover y cómo revertir con seguridad si algo falla — reduciendo downtime y el riesgo de pérdida de datos con un plan sencillo y ensayado.
Escenario, riesgos y objetivo del plan de rollback
En upgrades major de PostgreSQL, la replicación física no funciona entre versiones diferentes. Tu réplica de lectura 12 no seguirá a un primario 14. Por eso el plan debe considerar cómo migrar, cortar el tráfico y volver rápido.
El objetivo es: actualizar a 14 con la menor indisponibilidad posible, mantener un camino de retorno claro y documentado, y reducir la pérdida de datos si es necesario revertir.
La capacidad y las conexiones importan el día del corte. Si el pool se satura, puedes enfrentar colas y timeouts. Consulta prácticas en cómo diagnosticar y resolver 'Too many connections'.
- La réplica 12 no puede “convertirse” en 14 y seguir replicando desde el primario 12.
- Un rollback seguro requiere mantener el cluster 12 íntegro hasta confirmar la estabilidad en 14.
- Sin replicación inversa configurada, volver puede implicar perder los writes realizados después del corte.
- Planifica una ventana de mantenimiento corta con cambios congelados (freeze de DDL).
Prerequisitos y comprobaciones críticas antes del upgrade
Haz un inventario del entorno y reduce incertidumbres. Ten backups probados y un punto de recuperación (PITR) viable. Confirma espacio en disco para mantener el cluster 12 intacto mientras el 14 se estabiliza.
Valida: extensiones compatibles, parámetros, transacciones largas, claves foráneas deshabilitadas, replicación lógica habilitable (si optas por ella) y TTL de DNS/rutas para un flip rápido. Ajusta el pooler para reconexiones suaves.
A continuación, consultas útiles para mapear extensiones, sesiones largas y configuración de WAL/slots.
- Backups completos + restauración ensayada (PITR).
- Espacio libre para un cluster 14 junto al 12.
- Freeze de DDL y change freeze en la app durante la ventana.
- TTL de DNS/rutas reducido con antelación.
- Extensiones y versiones revisadas.
- Pooler (PgBouncer) preparado para la migración.
-- Extensões instaladas
SELECT extname, extversion FROM pg_extension ORDER BY 1;
-- Transações longas (potencial bloqueio no corte)
SELECT pid, usename, xact_start, state, query
FROM pg_stat_activity
WHERE xact_start IS NOT NULL AND state <> 'idle'
ORDER BY xact_start;
-- Nível de WAL e slots (para replicação lógica)
SHOW wal_level; -- deve ser 'logical' para pub/sub
SHOW max_replication_slots;
SHOW max_wal_senders;
Estrategias con réplica: qué camino elegir
Elige la aproximación considerando downtime, complejidad del rollback y recursos. La réplica de lectura ayuda a crear un clon consistente para pruebas o como base del 14, pero en algún momento tendrás que romper el seguimiento.
| Estrategia | Downtime | Rollback | Cuándo usar | Observaciones |
|---|---|---|---|---|
| A) pg_upgrade sobre copia del cluster 12 | Minutos a pocas horas (corte) | Sencillo: parar 14 y volver al 12 (pérdida de writes posteriores al corte) | Entornos con ventana corta y aceptación de rollback con posible pérdida mínima | Evitar --link; mantener el 12 intacto hasta estabilizar el 14 |
| B) Replicación lógica 12→14 (pub/sub) | Bajo a muy bajo | Medio: se puede volver al 12; para cero pérdida requiere replicación inversa o bloqueo de writes durante el smoke | Necesario para reducir downtime y validar 14 con datos reales | Requiere wal_level=logical y tratar tablas sin PK/replicación |
| C) Dump/restore (pg_dump/pg_restore) | Alto | Sencillo: no cortar si hay fallos | Bases de datos pequeñas y tolerancia a mayor indisponibilidad | Más simple, pero con mayor indisponibilidad |
Plan A: pg_upgrade usando la réplica (sin --link)
Usa la réplica como base del 14 sin arriesgar el primario 12. No uses --link si necesitas rollback garantizado; modifica archivos del cluster origen.
Resumen: para la réplica 12, copia el datadir a una nueva ubicación, inicializa el 14, ejecuta pg_upgrade, prueba, realiza el cutover y solo apaga el 12 después de la ventana de observación.
- Detener la réplica 12 y garantizar consistencia.
- Clonar el datadir a una nueva carpeta/disco.
- initdb del 14 y pg_upgrade --check.
- Ejecutar pg_upgrade y posanálisis (analyze/vacuum).
- Cutover corto: apuntar la app al 14.
- Mantener el 12 apagado e intacto para rollback.
# Parar a réplica 12 (ajuste caminhos conforme seu ambiente)
/path/to/old/bin/pg_ctl -D /pgdata/12/replica stop
# Clonar dados da réplica para área do upgrade (cópia completa)
rsync -aH --delete /pgdata/12/replica/ /pgdata/12/upgrade-copy/
# Inicializar cluster 14
/path/to/new/bin/initdb -D /pgdata/14/main
# Verificação prévia
/path/to/new/bin/pg_upgrade \
--old-datadir=/pgdata/12/upgrade-copy \
--new-datadir=/pgdata/14/main \
--old-bindir=/path/to/old/bin \
--new-bindir=/path/to/new/bin \
--check
# Executar upgrade (sem --link)
/path/to/new/bin/pg_upgrade \
--old-datadir=/pgdata/12/upgrade-copy \
--new-datadir=/pgdata/14/main \
--old-bindir=/path/to/old/bin \
--new-bindir=/path/to/new/bin
Plan B: replicación lógica 12→14 para reducir downtime
Con publicación/suscripción, el 14 recibe datos del 12 mientras validas rendimiento. Requisitos: wal_level=logical, PK en las tablas replicadas, manejar secuencias y DDL. Para rollback sin pérdida, mantén writes bloqueados durante el periodo de smoke o implementa replicación inversa con cuidado.
- Habilitar wal_level=logical en el 12 y reiniciar.
- Crear publicación en el 12 (filtrar tablas temporales).
- Inicializar 14 y crear la suscripción apuntando al 12.
- Monitorear sincronización y lag.
- Ensayar el corte: bloquear writes, esperar catch‑up y cambiar endpoint.
-- No 12 (primário)
ALTER SYSTEM SET wal_level = 'logical';
ALTER SYSTEM SET max_replication_slots = 10;
ALTER SYSTEM SET max_wal_senders = 10;
-- Reinicie o 12 para aplicar wal_level
-- Publicação (ajuste filtros conforme necessário)
CREATE PUBLICATION upgrade_pub FOR ALL TABLES;
-- No 14 (novo cluster)
-- Crie roles, extensions e estruturas antes da assinatura
CREATE SUBSCRIPTION upgrade_sub
CONNECTION 'host=old12 dbname=app user=replicator password=secret port=5432'
PUBLICATION upgrade_pub
WITH (copy_data = true, create_slot = true, slot_name = 'upgrade_slot');
Pruebas y validaciones antes del cutover
Ejecuta el script de análisis generado por pg_upgrade (o vacuumdb) para estadísticas adecuadas. Compara cardinalidad de tablas críticas, checksums de muestras y resultados de consultas conocidas. Ejecuta cargas de lectura/escritura de baja intensidad en staging conectado al 14.
Valida migraciones/DDL de la app y planes de rollback de esquema en Migraciones y rollbacks en PostgreSQL: guía. Si detectas regresión de plan o estadísticas, aplica técnicas en Cómo recuperar índices y estadísticas en PostgreSQL.
- Ejecutar analyze/vacuum para planes estables.
- Comparar conteos por tabla y sumas críticas.
- Reejecutar reportes pesados y consultas caché.
- Probar pooler y reconexión de la app.
- Comprobar permisos, roles y search_path.
# Após pg_upgrade, execute o script gerado
./analyze_new_cluster.sh
# Alternativa: analisar tudo com paralelismo
vacuumdb --all --analyze-in-stages --jobs=4
# Migrar objetos globais (roles, tablespaces)
pg_dumpall --globals-only | psql -h new14 -U postgres
Cutover controlado y ventana de rollback
Organiza un corte reversible. Bloquea writes de la app por un corto periodo para eliminar divergencia durante el smoke test. Drena sesiones antiguas, apunta el endpoint al 14 y monitorea latencia, locks y errores. Mantén el 12 apagado, intacto y listo para volver.
Si usas DNS, reduce el TTL días antes. Con HAProxy/PgBouncer, cambia el backend y prueba conexiones nuevas primero. Documenta el tiempo y las migraciones aplicadas.
- Bloqueo temporal de writes en la app/role.
- Drenar sesiones y finalizar conexiones activas.
- Flip del endpoint (DNS/HAProxy/PgBouncer).
- Smoke tests automatizados y manuales.
- Observación intensiva por el período acordado.
-- Exemplo: drenar sessões do banco 'app' (execute como superusuário)
SELECT pg_terminate_backend(pid)
FROM pg_stat_activity
WHERE datname = 'app' AND pid <> pg_backend_pid();
-- Opcional: tornar a role do app somente leitura durante o smoke
ALTER ROLE app SET default_transaction_read_only = on; -- reverter depois
Rollback seguro: criterios, ejecución y post‑rollback
Define criterios objetivos para revertir: corrupción detectada, regresión severa de rendimiento, fallos críticos en la app o incompatibilidad de extensiones. El rollback debe ser rápido y repetible.
Ejecución típica: para el 14, apunta endpoints de vuelta al 12 y libera writes solo tras verificaciones básicas. Registra los writes perdidos en el 14 (si los hubo) y evalúa la reconciliación manual.
Para reducir pérdida de datos, puedes mantener la app con writes bloqueados durante el smoke. Alternativamente, implementa replicación lógica inversa 14→12 antes del corte, consciente de la complejidad y conflictos. Como medida extrema, recurre a PITR; consulta recuperación point‑in‑time.
Este es exactamente el escenario en el que merece la pena preparar “cómo planificar y ejecutar rollback seguro al actualizar la versión major del PostgreSQL 12→14 en producción con réplica de lectura”: criterios claros, pasos ensayados y comunicación continua con las partes involucradas.
- Criterios objetivos y aprobadores claros.
- Pasos de reversión ensayados y cronometrados.
- Comunicación al negocio y registro del impacto.
- Plan de reconciliación de datos, si es necesario.
- Checklist para reabrir el tráfico en el 12.
Preguntas frecuentes
¿Puedo mantener la réplica 12 siguiendo al primario 14 después del upgrade?
No. La replicación física es específica de versión. Los clusters 12 y 14 no pueden replicarse entre sí por streaming. Usa side‑by‑side con pg_upgrade en copia, o replicación lógica (publicación/suscripción) para mover datos entre versiones major diferentes.
¿Cómo minimizar el downtime en el corte hacia el 14?
Prepara todo con antelación: análisis de estadísticas, roles y permisos migrados, prueba en staging, TTL de DNS bajo, automatización del flip vía HAProxy/PgBouncer y bloqueo temporal de writes. Con replicación lógica el 14 llega casi sincronizado y el corte es rápido.
¿Es posible rollback sin pérdida de datos?
Es posible pero más complejo. Debes bloquear writes durante el smoke test o configurar replicación lógica inversa 14→12 con estrategias de resolución de conflictos. Sin esto, volver al 12 implica descartar los writes hechos en el 14 después del corte.
¿Qué debo comprobar sobre las extensiones en el upgrade 12→14?
Confirma que cada extensión usada tenga una versión compatible en 14 y un plan de migración. Actualiza extensiones en el momento adecuado y valida funciones, tipos e índices asociados. Ante dudas, aísla el esquema de la extensión en tests antes de cortar el tráfico.
¿Necesito ejecutar VACUUM/ANALYZE después del upgrade?
Sí. Las estadísticas actualizadas son vitales para buenos planes de consulta. Ejecuta el script generado por pg_upgrade o vacuumdb --analyze‑in‑stages. Tras el corte, monitorea consultas críticas y ajusta costos, índices y parámetros si notas regresión.
¿Cómo tratar secuencias en la replicación lógica?
Las secuencias no se replican automáticamente. Inicializa valores manualmente en el 14 después de la copia inicial o sincronízalas con scripts. Asegura que no haya solapamiento de valores y valida claves antes de liberar writes en el nuevo cluster.
¿Quieres revisar tu plan de upgrade y rollback?
Si necesitas una segunda opinión sobre el diseño del corte, validaciones y plan de retorno, hablemos sobre tu contexto y restricciones.
Hablar sobre el upgradeVer también
- Guía práctica: configurar failover activo‑pasivo entre dos VPS con Keepalived, HAProxy y lsyncd para uploads sincronizados
- Guía: checklist técnico para preparar un VPS Debian con Docker Compose para aplicaciones PHP en producción
- Guía práctica para dimensionamiento de VPS y tuning de PHP‑FPM para tiendas Magento/OpenMage con picos estacionales: del dimensionamiento a la prueba de carga
- Guía: cómo planificar y ejecutar pruebas de carga en aplicaciones PHP monolito usando k6 y Docker Compose — paso a paso