Guia prático: como recuperar uma tabela excluída no PostgreSQL usando point-in-time recovery sem downtime

Por · Publicado em · Atualizado em · 9 min de leitura

frontal de rack com unidades de servidor e luzes de status verdes
Close-up de servidores em rack, adequado para temas de backup e recuperação. Foto: heladodementa / Pixabay

Como recuperar uma tabela excluída no PostgreSQL usando point-in-time recovery sem downtime? A resposta é restaurar um servidor temporário até antes do DROP, extrair somente a tabela e dependências, e reintroduzi-las no banco de produção com bloqueios mínimos. Assim você valida os dados antes do swap e evita parar o ambiente principal.

Quando usar PITR para recuperar só a tabela

Use point-in-time recovery quando você tem backups base e WALs arquivados e precisa voltar a um estado anterior sem interromper o ambiente de produção. A ideia é restaurar para um servidor temporário, encontrar a versão boa da tabela e importar de volta.

Esse é exatamente o caminho de como recuperar uma tabela excluída no PostgreSQL usando point-in-time recovery sem downtime quando você precisa validar o dado e reduzir riscos antes do retorno ao banco principal.

  • Você sabe (ou consegue estimar) o horário do DROP.
  • Há base backup recente e archiving contínuo dos WALs.
  • A tabela não é UNLOGGED (essas não entram em WAL).
  • Você pode levantar uma instância temporária compatível.

Pré-requisitos e limitações do método

Sem archiving contínuo prévio, o PITR completo pode não ser possível. Também é essencial restaurar em versão major idêntica à produção para evitar diferenças de formato. Nunca rode o PITR no servidor de produção: sempre use um host/container temporário com armazenamento suficiente.

Backups e monitoramento recorrentes reduzem drasticamente o impacto de incidentes. Se você ainda não tem rotina sólida, avalie práticas de hardening e backup em servidores Linux em hardening, backup e monitoramento.

  • wal_level=replica, archive_mode=on e archive_command configurados.
  • Base backup disponível de antes do incidente.
  • Espaço em disco para restaurar dados e WALs.
  • Acesso aos arquivos de archive (ex.: NFS/S3/volume local).
  • Mesma versão major do PostgreSQL entre produção e recuperação.
# postgresql.conf (produção)
wal_level = replica
archive_mode = on
archive_command = 'rsync -a %p /mnt/pg_wal_archive/%f'
max_wal_senders = 10
hot_standby = on

Passo 1 — Descobrir o instante exato do DROP

Defina um recovery_target_time seguro (logo antes da exclusão). Utilize logs de aplicação, auditoria, ferramentas de observabilidade e o fuso horário da instância. Preferencialmente, selecione alguns minutos antes do incidente para garantir que a tabela exista no ponto escolhido.

Erros comuns aqui envolvem fuso horário. Confirme o timezone atual do banco e converta o horário do incidente, se necessário.

  • Cruze logs de app, auditoria e deploys recentes.
  • Valide timezone para evitar restaurar para o horário errado.
  • Considere margem de segurança de 2–5 minutos antes do DROP.
-- Confirme o timezone efetivo da instância
SHOW TimeZone;

Passo 2 — Restaurar um servidor temporário com PITR

Restaure um base backup de antes do incidente em um novo diretório de dados. Configure o restore_command para acessar os WALs arquivados e aponte o recovery_target_time. Ao iniciar, o Postgres reexecuta os WALs até o instante e promove a instância.

  • Use versão major idêntica à produção.
  • Pense na segurança: isole rede/credenciais do servidor temporário.
  • Escolha storage rápido para acelerar a aplicação dos WALs.
# Exemplo (PostgreSQL 12+): diretório /pgdata_rec
# 1) Extraia o base backup
sudo -u postgres tar -xvf /backups/base_backup_before_drop.tar -C /pgdata_rec

# 2) Configure parâmetros de recovery
cat >> /pgdata_rec/postgresql.conf <<'EOF'
restore_command = 'cp /mnt/pg_wal_archive/%f %p'
recovery_target_time = '2026-09-30 14:23:00+00'
recovery_target_action = 'promote'
recovery_target_timeline = 'latest'
EOF

# 3) Sinalize o recovery
sudo -u postgres touch /pgdata_rec/recovery.signal

# 4) Inicie a instância temporária
sudo -u postgres pg_ctl -D /pgdata_rec -l /pgdata_rec/logfile start

# Acompanhe os logs até a promoção (instância pronta para leitura)

Passo 3 — Extrair a tabela e dependências do servidor recuperado

Com a instância temporária pronta, faça dump apenas da tabela e objetos associados (sequências e, se aplicável, tipos e funções dependentes). O formato custom (-Fc) facilita restaurações seletivas. Se a tabela for particionada, faça dump das partições necessárias também.

  • Inclua sequências relacionadas para preservar valores.
  • Revise dependências (views, materialized views, FKs).
  • Para tabelas grandes, prefira rede local de alta vazão.
# Exemplo: recuperar public.pedidos e a sequência de ID
pg_dump -h 10.0.0.50 -U postgres -d appdb -Fc \
  -t public.pedidos -t public.pedidos_id_seq \
  -f /tmp/pedidos.dump

Passo 4 — Restaurar no banco de produção com bloqueios mínimos

Se a tabela não existe mais, a restauração é direta. Se ela foi recriada após o incidente, prefira restaurar para um nome temporário, validar e depois fazer troca atômica de nomes. Índices grandes podem ser recriados com CREATE INDEX CONCURRENTLY para reduzir bloqueio. Triggers e FKs exigem atenção especial.

  • Restaure para tabela temporária quando houver tabela atual.
  • Crie índices CONCURRENTLY fora de transação para menor impacto.
  • A troca de nomes usa bloqueio curto (ACCESS EXCLUSIVE), normalmente imperceptível.
  • Ajuste a sequência após importar os dados.
Opção de restauração Duração do bloqueio Observações
Restauração direta (tabela não existe) Baixa Importa e usa; índices normais podem bloquear mais.
Restauração em tabela temporária + swap Muito baixa Permite validação e troca rápida por RENAME.
Índices CONCURRENTLY Muito baixa Crie antes do swap; não usar dentro de transação.
# 1) Restaurar para uma tabela temporária
pg_restore -h prod-db -U postgres -d appdb -j 4 \
  -t public.pedidos -t public.pedidos_id_seq /tmp/pedidos.dump \
  --no-owner --no-privileges

# 2) Se a tabela atual existe, faça swap rápido
psql -h prod-db -U postgres -d appdb <<'SQL'
BEGIN;
-- Se necessário, solte chaves estrangeiras que apontam para a tabela antiga aqui, e recrie após o swap.
ALTER TABLE IF EXISTS public.pedidos RENAME TO pedidos_old;
ALTER TABLE public.pedidos RENAME TO pedidos_restaurada; -- caso o dump tenha recriado com o mesmo nome
ALTER TABLE public.pedidos_restaurada RENAME TO pedidos;
COMMIT;

-- 3) Ajuste sequência após a carga
SELECT setval('public.pedidos_id_seq', (SELECT COALESCE(MAX(id),1) FROM public.pedidos)+1, false);
SQL

Validação pós‑restauração e riscos comuns

Antes do swap (ou logo após, se não havia tabela), valide estrutura e contagens. Compare checks básicos com a instância temporária. Monitore locks e impacto na aplicação. Para investigar bloqueios e contenção em produção, veja práticas no guia de jobs e bloqueios em PostgreSQL: auditar e otimizar jobs cron.

  • Comparar COUNT(*), MIN/MAX de chaves, e amostras aleatórias.
  • Validar constraints e FKs (ativar/checar, se tiver desativado).
  • Reaplicar grants e políticas de segurança (RLS) se existirem.
  • Verificar sequences e rotinas de manutenção (VACUUM/ANALYZE).
-- Exemplos de checagens rápidas
SELECT COUNT(*) FROM public.pedidos;
SELECT MIN(id), MAX(id) FROM public.pedidos;
ANALYZE public.pedidos;

E se o archiving não estava ativo? Alternativas práticas

Sem archive_mode ligado e sem base backups, recuperar via PITR clássico pode ser inviável. Avalie: snapshots do sistema de arquivos anteriores ao incidente, restauração de backups do provedor de nuvem, ou recuperação a partir de uma réplica física que ainda não aplicou o DROP. Quando viável, restaure em instância separada e siga o mesmo processo de extração/importação da tabela.

  • Snapshots de volume/VM anteriores ao incidente.
  • Restauração em serviços gerenciados com PITR ativado.
  • Réplica física atrasada (se existir) para extrair a tabela.
  • Ferramentas de terceiros têm limitações e riscos.

Como evitar o próximo incidente: práticas e arquitetura

Implemente archiving contínuo, políticas de retenção e testes periódicos de restauração. Para reverter mudanças de schema com segurança, use versionamento de banco e pipelines de migração confiáveis: confira o guia de versionamento de banco de dados. Para reduzir ainda mais downtime, considere replicação lógica/CDC para swaps controlados em produção: veja a estratégia de migração zero‑downtime com CDC.

  • Testes de restauração regulares (table‑level e cluster‑level).
  • Retenção adequada de WAL conforme RPO/RTO do negócio.
  • Alertas de archiving e espaço em disco.
  • Migrações com rollback e janelas de feature flags.

Perguntas frequentes

Consigo recuperar apenas uma tabela com PITR no PostgreSQL?

Sim, mas indiretamente. Você faz PITR para um servidor temporário até antes do incidente e então exporta somente a tabela (e dependências) com pg_dump, importando de volta na produção com bloqueios mínimos.

E se eu não tinha archive_mode ligado ou base backups?

O PITR clássico não será possível. Tente restaurar um snapshot do sistema de arquivos, usar backups do provedor de nuvem ou extrair da réplica física se ela não aplicou o DROP. No futuro, ative archiving e rotinas de backup testadas.

A restauração sem downtime é realmente sem bloqueios?

Você evita parada do banco principal restaurando em instância separada. A importação pode exigir bloqueios breves (por exemplo, no RENAME). Em geral, o impacto é imperceptível se planejar índices e a troca de nomes corretamente.

Como lido com sequências associadas à tabela?

Inclua as sequências no dump e, após importar, ajuste com setval para alinhar o próximo valor ao MAX(id) da tabela. Assim você evita colisões ou violações de chave primária em inserções futuras.

Preciso usar a mesma versão do PostgreSQL na instância temporária?

Sim, utilize a mesma versão major para restaurar base backups e aplicar WALs. Diferenças de versão major podem impedir a recuperação ou introduzir incompatibilidades de formato e collation.

Como escolho o recovery_target_time correto?

Use logs de aplicação e auditoria para identificar o horário do DROP e recupere alguns minutos antes, considerando o timezone do servidor. Validar o ponto escolhido evita restaurar para um estado ainda inconsistente.

Precisa recuperar uma tabela agora com mínimo impacto?

Podemos avaliar seu cenário, definir o ponto de recuperação e conduzir a restauração segura em uma instância temporária, com validação e importação de baixo risco.

Falar sobre recuperação PITR

Veja também