Point-in-time recovery: restaurando para um momento específico
1. Fundamentos do Point-in-time Recovery (PITR)
Point-in-time recovery (PITR) é uma técnica de recuperação de bancos de dados que permite restaurar o sistema para um estado consistente em qualquer instante específico do passado. Diferente de um backup completo tradicional, que restaura apenas o estado do banco no momento em que o backup foi feito, o PITR possibilita "voltar no tempo" para um ponto exato entre backups.
A base do PITR está na combinação de dois elementos: um backup completo (full backup) e uma sequência contínua de logs de transações (WAL — Write-Ahead Log). Enquanto o backup completo fornece uma imagem base do banco, os logs registram todas as mudanças subsequentes, permitindo que o sistema seja reconstruído até qualquer ponto intermediário.
Os casos de uso mais comuns incluem:
- Erro humano: um usuário executa DELETE sem cláusula WHERE e percebe minutos depois
- Corrupção lógica: uma migração de schema mal-sucedida introduz inconsistências
- Rollback de migração: necessidade de retornar ao estado anterior a uma atualização de versão
2. Arquitetura por Trás do PITR
O coração do PITR é o Write-Ahead Log (WAL). No PostgreSQL, por exemplo, toda modificação no banco é primeiro registrada no WAL antes de ser aplicada aos arquivos de dados. Isso garante durabilidade e possibilita a reconstrução temporal.
Cada entrada no WAL possui um Log Sequence Number (LSN) — um identificador único e crescente que indica a posição exata do registro no log. Além do LSN, cada transação é associada a um timestamp e a um XID (Transaction ID), permitindo múltiplas formas de especificar o ponto de recuperação.
A arquitetura do PITR segue esta dependência:
Backup completo (base) + WALs sequenciais = Banco em qualquer ponto T
Se um WAL intermediário estiver faltante, a recuperação para pontos posteriores a ele se torna impossível. Por isso, a continuidade dos logs é crítica.
3. Estratégias de Backup para Viabilizar o PITR
Para habilitar o PITR, é necessário configurar o banco para arquivar os WALs continuamente. No PostgreSQL, isso envolve:
# postgresql.conf
wal_level = replica
archive_mode = on
archive_command = 'cp %p /var/lib/pgsql/archive/%f'
A estratégia típica de backup para PITR é:
- Backup completo inicial (base backup) — usando
pg_basebackupou ferramentas comopgBackRest - Backups incrementais/diferenciais — capturam apenas blocos alterados desde o último backup completo
- Arquivamento contínuo de WAL — cada segmento de WAL (geralmente 16 MB) é copiado para um diretório de archive
Políticas de retenção devem equilibrar espaço em disco versus necessidade de recuperação. Uma prática comum é manter WALs dos últimos 7 a 30 dias, combinados com backups completos semanais.
Exemplo de backup completo com pg_basebackup:
pg_basebackup -D /backup/base_20250325 -Ft -z -P -X stream
4. Executando a Restauração Point-in-time
O processo de restauração PITR no PostgreSQL segue estes passos:
Passo 1: Parar o servidor
pg_ctl stop -D /var/lib/pgsql/15/data
Passo 2: Restaurar o backup completo
rm -rf /var/lib/pgsql/15/data/*
tar -xzf /backup/base_20250325/base.tar.gz -C /var/lib/pgsql/15/data
Passo 3: Configurar o recovery target
Crie o arquivo recovery.signal no diretório de dados e configure postgresql.conf (ou recovery.conf em versões antigas):
# postgresql.conf (ou recovery.conf no PostgreSQL < 12)
restore_command = 'cp /var/lib/pgsql/archive/%f %p'
recovery_target_time = '2025-03-25 14:30:00 BRT'
recovery_target_action = 'promote'
Passo 4: Iniciar o servidor em modo recovery
pg_ctl start -D /var/lib/pgsql/15/data
O PostgreSQL aplicará automaticamente os WALs até o timestamp especificado e, em seguida, promoverá o banco para leitura/escrita.
Especificando o target
O target pode ser definido de várias formas:
recovery_target_time = '2025-03-25 14:30:00' -- timestamp
recovery_target_xid = '1234567' -- transaction ID
recovery_target_lsn = '0/1A2B3C4D' -- LSN
recovery_target_name = 'before_migration' -- nome de restore point
5. Tratamento de Cenários Complexos no PITR
Recuperação até o último WAL disponível
Se você não especificar um target, o PostgreSQL aplicará todos os WALs disponíveis, recuperando até o último registro possível:
recovery_target_time = '' -- ou omitir a diretiva
WALs corrompidos ou faltantes
Se um WAL necessário estiver faltante, a recuperação para após o último WAL íntegro. Para mitigar esse risco:
- Configure
archive_timeoutpara forçar o arquivamento frequente (ex.: a cada 60 segundos) - Use ferramentas como
pg_waldumppara inspecionar segmentos suspeitos:
pg_waldump /var/lib/pgsql/archive/00000001000000000000001A
PITR em ambientes replicados
Em replicação streaming, o standby mantém seus próprios WALs. Para fazer PITR em um standby:
- Promova o standby a primário (se necessário)
- Faça o backup do standby promovido
- Configure recovery_target no novo servidor
Em replicação cascata (standby de standby), a complexidade aumenta pois os WALs podem chegar com atraso. Nesses casos, é recomendável usar um repositório centralizado de WALs.
6. Validação e Boas Práticas Pós-Restauração
Após a restauração, valide a integridade dos dados:
# Verificar consistência do banco
pg_checksums -c /var/lib/pgsql/15/data
# Inspecionar transações recentes com pg_waldump
pg_waldump --start=0/1A2B3C00 --end=0/1A2B3DFF /var/lib/pgsql/archive/
Boas práticas essenciais:
- Teste periodicamente: execute restaurações PITR em ambiente de staging a cada mês
- Documente o processo: inclua comandos exatos e tempos esperados
- Monitore o archive: verifique se os WALs estão sendo copiados corretamente:
SELECT * FROM pg_stat_archiver;
- Mantenha backups completos regulares: o PITR depende de um base backup íntegro
7. Comparação com Ferramentas e Abordagens Alternativas
PITR nativo vs. Snapshot de disco (LVM/ZFS)
| Característica | PITR nativo | Snapshot (LVM/ZFS) |
|---|---|---|
| Granularidade temporal | Segundo a segundo | Instantâneo fixo |
| Espaço em disco | Alto (WALs contínuos) | Baixo (copy-on-write) |
| Velocidade de recovery | Lenta (replay de WALs) | Rápida (montagem do snapshot) |
| Dependência de ferramenta | Nenhuma (nativo) | Sistema de arquivos |
PITR vs. Replicação lógica contínua
A replicação lógica (como pglogical ou Decoding) permite manter um banco standby sincronizado quase em tempo real, mas não substitui o PITR:
- PITR: recupera qualquer ponto no tempo, mesmo antes da replicação existir
- Replicação lógica: mantém um clone atualizado, mas não permite "voltar" no histórico
Limitações do PITR
- Dependência de WAL contínuo: se um WAL for perdido, a recuperação para além dele é impossível
- Latência de recovery: bancos muito grandes ou com muitas transações podem levar horas para aplicar todos os WALs
- Espaço em disco: manter meses de WALs requer planejamento de armazenamento
Referências
-
PostgreSQL Documentation: Continuous Archiving and Point-in-Time Recovery (PITR) — Documentação oficial do PostgreSQL sobre arquivamento contínuo e PITR, com exemplos completos de configuração e restauração.
-
PostgreSQL: pg_waldump — Display WAL Log Contents — Referência completa da ferramenta pg_waldump para inspeção de logs WAL, essencial para diagnóstico e validação pós-restauração.
-
Percona Blog: Point-in-Time Recovery in PostgreSQL — Best Practices — Artigo técnico da Percona abordando práticas recomendadas, configuração de archive e estratégias de teste para PITR.
-
Cybertec: PostgreSQL Point-in-Time Recovery Step by Step — Tutorial prático passo a passo demonstrando a execução completa de uma restauração PITR com exemplos de comandos.
-
EDB: Understanding PostgreSQL WAL and Point-in-Time Recovery — Explicação aprofundada sobre a arquitetura WAL e como ela viabiliza o PITR, incluindo conceitos de LSN e XID.