Como planejar e executar rollback seguro ao atualizar versão major do PostgreSQL (12→14) em produção com réplica de leitura — guia prático

Por · Publicado em · 10 min de leitura

Guia prático de rollback seguro no upgrade major do PostgreSQL 12→14 com réplica de leitura
Foto: panumas nikhomkhai / Pexels

Guia: como planejar e executar rollback seguro ao atualizar versão major do PostgreSQL 12→14 em produção com réplica de leitura. Você verá pré‑requisitos, quando usar pg_upgrade ou replicação lógica, como conduzir o cutover e como reverter com segurança se algo sair do esperado — reduzindo downtime e risco de perda de dados com um plano simples e ensaiado.

Cenário, riscos e objetivo do plano de rollback

Em upgrades major do PostgreSQL, a replicação física não funciona entre versões diferentes. Sua réplica de leitura 12 não seguirá um primário 14. Por isso, o plano precisa considerar como migrar, cortar o tráfego e voltar rápido.

O objetivo é: atualizar para 14 com o mínimo de indisponibilidade, manter um caminho de retorno claro e documentado, e reduzir perda de dados caso seja necessário reverter.

Capacidade e conexões importam no dia do corte. Se o pool estourar, você pode enfrentar fila e timeouts. Veja práticas em como diagnosticar e resolver 'Too many connections'.

  • A réplica 12 não pode “virar” 14 e continuar seguindo o primário 12.
  • Rollback seguro requer manter o cluster 12 íntegro até confirmar estabilidade no 14.
  • Sem replicação reversa configurada, rollback pode implicar perda dos writes feitos após o corte.
  • Planeje janela de manutenção curta com mudanças congeladas (freeze de DDL).

Pré‑requisitos e checagens críticas antes do upgrade

Faça um inventário do ambiente e reduza incertezas. Tenha backups testados e um ponto de recuperação (PITR) viável. Confirme espaço em disco para manter o cluster 12 intacto enquanto o 14 estabiliza.

Valide: extensões compatíveis, parâmetros, longas transações, chaves estrangeiras desabilitadas, replicação lógica habilitável (se optar por ela), e TTL de DNS/rotas para um flip rápido. Ajuste o pooler para reconexão suave.

Abaixo, consultas úteis para mapear extensões, sessões longas e configuração de WAL/slots.

  • Backups completos + restauração ensaiada (PITR).
  • Espaço livre para um cluster 14 ao lado do 12.
  • Freeze de DDL e change freeze no app durante a janela.
  • TTL de DNS/rotas reduzido com antecedência.
  • Extensões e versões revisadas.
  • Pooler (PgBouncer) preparado para migração.
-- 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;

Estratégias com réplica: qual caminho escolher

Escolha a abordagem considerando downtime, complexidade de rollback e recursos. A réplica de leitura ajuda a criar um clone consistente para testes ou como base do 14, mas você precisará quebrar o seguimento em algum momento.

Estratégia Downtime Rollback Quando usar Observações
A) pg_upgrade em cópia do cluster 12 Minuto(s) a baixa hora(s) (corte) Simples: parar 14 e voltar 12 (perda de writes pós‑corte) Ambientes com janela curta e aceitação de rollback com possível perda mínima Evite --link; mantenha o 12 intacto até estabilizar o 14
B) Replicação lógica 12→14 (pub/sub) Baixo a muito baixo Médio: pode voltar ao 12; para zero perda exige replicação reversa ou bloqueio de writes no smoke Necessário reduzir downtime e validar 14 com dados reais Exige wal_level=logical e tratar tabelas sem PK/replicação
C) Dump/restore (pg_dump/pg_restore) Alto Simples: não cortar se houver falhas Bancos menores e tolerância a parada Mais simples, mas com indisponibilidade maior

Use a réplica como base do 14 sem arriscar o primário 12. Não use --link se você precisa de rollback garantido; ele altera arquivos do cluster de origem.

Resumo: pare a réplica 12, copie o datadir para um novo local, inicialize o 14, rode pg_upgrade, teste, corte, e só então desligue o 12 depois da janela de observação.

  • Parar réplica 12 e garantir consistência.
  • Clonar datadir para nova pasta/disco.
  • initdb do 14 e pg_upgrade --check.
  • Executar pg_upgrade e pós‑análise (analyze/vacuum).
  • Cutover curto: apontar app para o 14.
  • Manter 12 desligado 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

Plano B: replicação lógica 12→14 para reduzir downtime

Com publicação/assinatura, o 14 recebe dados do 12 enquanto você valida performance. Requisitos: wal_level=logical, PK nas tabelas replicadas, lidar com sequências e DDL. Para rollback sem perda, mantenha writes bloqueados por um período de smoke ou implemente replicação reversa com cuidado.

  • Habilitar wal_level=logical no 12 e reiniciar.
  • Criar publicação no 12 (filtre tabelas temporárias).
  • Inicializar 14 e criar assinatura apontando para o 12.
  • Acompanhar sincronização e lag.
  • Ensaiar o corte: bloquear writes, esperar catch‑up e mudar 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');

Testes e validações antes do cutover

Execute o script de análise gerado pelo pg_upgrade (ou vacuumdb) para estatísticas adequadas. Compare cardinalidade de tabelas críticas, checksums de amostras e resultados de queries conhecidas. Rode cargas de leitura/gravação de baixa intensidade em staging conectado ao 14.

Valide migrations/DDL do app e planos de rollback de schema em Migrations e rollbacks em PostgreSQL: guia. Se notar regressão de plano ou estatísticas, veja técnicas em Como recuperar índices e stats no PostgreSQL.

  • Rodar analyze/vacuum para planos estáveis.
  • Comparar contagens por tabela e somatórios críticos.
  • Reexecutar relatórios pesados e consultas de cache.
  • Testar pooler e reconexão do app.
  • Conferir permissões, roles e 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 e janela de rollback

Organize um corte reversível. Bloqueie writes do app por curto período para eliminar divergência durante o teste de fumaça. Drene sessões antigas, aponte o endpoint para o 14 e monitore latência, locks e erros. Mantenha o 12 desligado, intacto e pronto para voltar.

Se você usa DNS, reduza TTL dias antes. Com HAProxy/PgBouncer, troque o backend e teste conexões novas primeiro. Documente o tempo e as migrações aplicadas.

  • Bloqueio temporário de writes no app/role.
  • Drenar sessões e encerrar conexões ativas.
  • Flip de endpoint (DNS/HAProxy/PgBouncer).
  • Smoke tests automatizados e manuais.
  • Observação intensiva por um 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: critérios, execução e pós‑rollback

Defina critérios objetivos para reverter: corrupção detectada, regressão severa de performance, falhas críticas no app, ou incompatibilidade de extensões. O rollback precisa ser rápido e repetível.

Execução típica: pare o 14, aponte endpoints de volta ao 12, libere writes apenas após verificações básicas. Registre os writes perdidos no 14 (se houver) e avalie reconciliação manual.

Para reduzir perda de dados, você pode manter o app com writes bloqueados durante o smoke. Alternativamente, implemente replicação lógica reversa 14→12 antes do corte, ciente da complexidade e de conflitos. Como medida extrema, recorra a PITR; veja recuperação por point‑in‑time.

Este é exatamente o cenário em que vale preparar “como planejar e executar rollback seguro ao atualizar versão major do PostgreSQL 12→14 em produção com réplica de leitura”: critérios claros, passos ensaiados e comunicação contínua com as partes envolvidas.

  • Critérios objetivos e aprovadores claros.
  • Passos de reversão ensaiados e cronometrados.
  • Comunicação ao negócio e registro de impacto.
  • Plano de reconciliação de dados, se necessário.
  • Checklist para reabrir o tráfego no 12.

Perguntas frequentes

Posso manter a réplica 12 seguindo o primário 14 após o upgrade?

Não. A replicação física é específica de versão. Clusters 12 e 14 não replicam entre si por streaming. Use side‑by‑side com pg_upgrade em cópia, ou replicação lógica (publicação/assinatura) para mover dados entre versões major diferentes.

Como minimizar downtime no corte para o 14?

Prepare tudo com antecedência: análise de estatísticas, roles e permissões migradas, teste em staging, TTL de DNS baixo, automação de flip via HAProxy/PgBouncer e bloqueio temporário de writes. Com replicação lógica, o 14 chega quase sincronizado e o corte é rápido.

É possível rollback sem perda de dados?

Possível, mas mais complexo. Você precisa bloquear writes durante o teste de fumaça ou configurar replicação lógica reversa 14→12 com estratégias de resolução de conflitos. Sem isso, voltar ao 12 implica descartar os writes feitos no 14 após o corte.

O que devo checar sobre extensões no upgrade 12→14?

Confirme se cada extensão usada possui versão compatível no 14 e plano de migração. Atualize extensões no momento certo e valide funções, tipos e índices associados. Em caso de dúvidas, isole o schema da extensão em testes antes de cortar o tráfego.

Preciso rodar VACUUM/ANALYZE após o upgrade?

Sim. Estatísticas atualizadas são vitais para bons planos de consulta. Rode o script gerado pelo pg_upgrade ou vacuumdb --analyze‑in‑stages. Após o corte, monitore consultas críticas e ajuste custos, índices e parâmetros se notar regressão.

Como tratar sequências na replicação lógica?

Sequências não são replicadas automaticamente. Inicialize valores manualmente no 14 após a cópia inicial ou sincronize usando scripts. Garanta que não haja sobreposição de valores e valide chaves antes de liberar writes no novo cluster.

Quer revisar seu plano de upgrade e rollback?

Se você precisa de uma segunda opinião no desenho do corte, validações e plano de retorno, vamos conversar sobre seu contexto e restrições.

Conversar sobre o upgrade

Veja também