TL;DR — Resumo Rápido
Estratégias de backup no PostgreSQL: pg_dump, pg_dumpall, pg_basebackup, WAL archiving, PITR e scripts automatizados com rotação e upload para S3.
O PostgreSQL é a espinha dorsal de inúmeras aplicações em produção — perder dados sem um plano de restauração testado é catastrófico. Este guia cobre todas as principais estratégias de backup e restauração no PostgreSQL: backups lógicos com pg_dump e pg_dumpall, backups físicos com pg_basebackup, WAL archiving contínuo para recuperação ponto no tempo (PITR), scripts automatizados, criptografia e upload para a nuvem.
Pré-requisitos
- PostgreSQL 14 ou superior (comandos funcionam desde a versão 12).
- O usuário
postgresou um role com privilégiospg_read_all_data/SUPERUSER. - Espaço em disco suficiente (pelo menos 1,5× o tamanho dos seus bancos de dados).
aws-cliourcloneinstalado se usar armazenamento em nuvem.gpginstalado para backups criptografados.
Backups Lógicos com pg_dump
pg_dump exporta um único banco de dados para SQL ou formato binário personalizado — o método de backup mais portável.
Backup Completo do Banco de Dados
# Formato personalizado (recomendado) — comprimido, suporta restauração seletiva
pg_dump -U postgres -Fc -d meudb -f /backup/meudb_$(date +%Y%m%d).pgdump
# SQL simples — legível, restaurar com psql
pg_dump -U postgres -Fp -d meudb -f /backup/meudb_$(date +%Y%m%d).sql
Backup de Uma Única Tabela
pg_dump -U postgres -Fc -d meudb -t public.pedidos -f /backup/pedidos_$(date +%Y%m%d).pgdump
Formato Personalizado vs SQL Simples
| Recurso | Formato Personalizado (-Fc) | SQL Simples (-Fp) |
|---|---|---|
| Compressão | Integrada (zlib) | Não (use gzip separado) |
| Restauração seletiva | Sim (-t, -n, -T) | Não |
| Restauração paralela | Sim (pg_restore -j) | Não |
| Legível por humanos | Não | Sim |
| Ferramenta de restauração | pg_restore | psql |
Use formato personalizado para backups em produção.
Backups de Cluster com pg_dumpall
pg_dumpall faz backup do cluster PostgreSQL completo: todos os bancos, roles e tablespaces.
pg_dumpall -U postgres -f /backup/cluster_$(date +%Y%m%d).sql
pg_dumpall -U postgres --globals-only -f /backup/globals_$(date +%Y%m%d).sql
Restauração:
psql -U postgres -f /backup/cluster_20260322.sql
Backups Físicos com pg_basebackup
pg_basebackup cria uma cópia binária do diretório de dados do PostgreSQL — base para PITR e servidores standby.
pg_basebackup -U replicator -h localhost -D /backup/base \
-Ft -z -P --wal-method=stream
Requisitos:
- Role com privilégio
REPLICATION:CREATE ROLE replicator REPLICATION LOGIN PASSWORD '...'; max_wal_senders >= 2nopostgresql.conf.- Entrada no
pg_hba.conf:host replication replicator 127.0.0.1/32 md5
WAL Archiving e Recuperação Ponto no Tempo
O WAL archiving combinado com um backup base habilita o PITR — restaurar para qualquer momento passado.
Habilitar WAL Archiving
Edite /etc/postgresql/16/main/postgresql.conf:
wal_level = replica
archive_mode = on
archive_command = 'cp %p /backup/wal_archive/%f'
archive_timeout = 300
Para S3:
archive_command = 'aws s3 cp %p s3://meus-backups-pg/wal/%f'
sudo systemctl reload postgresql
Verificar que o Arquivamento Funciona
SELECT last_archived_wal, last_archived_time, last_failed_wal
FROM pg_stat_archiver;
Recuperação para um Ponto Específico
- Pare o PostgreSQL e substitua o diretório de dados pelo backup base.
- Crie
recovery.signalno diretório de dados (PostgreSQL 12+). - Configure os parâmetros de recuperação no
postgresql.conf:
restore_command = 'cp /backup/wal_archive/%f %p'
recovery_target_time = '2026-03-22 14:30:00'
recovery_target_action = 'promote'
- Inicie o PostgreSQL — ele reproduzirá o WAL até o momento especificado.
Restauração a partir de Backups
Restaurar com pg_restore (Formato Personalizado)
createdb -U postgres meudb_restaurado
pg_restore -U postgres -d meudb_restaurado /backup/meudb_20260322.pgdump
# Restauração paralela
pg_restore -U postgres -j 4 -d meudb_restaurado /backup/meudb_20260322.pgdump
# Restaurar apenas uma tabela
pg_restore -U postgres -d meudb_restaurado -t public.pedidos /backup/meudb_20260322.pgdump
Restaurar com psql (SQL Simples)
psql -U postgres -d meudb_restaurado -f /backup/meudb_20260322.sql
Visualizar Conteúdo de um Backup
pg_restore --list /backup/meudb_20260322.pgdump | grep TABLE
Scripts de Backup Automatizado
Script Diário com Rotação
#!/bin/bash
# /usr/local/bin/pg-backup.sh
set -euo pipefail
BACKUP_DIR="/backup/postgresql"
DIAS_MANTER=7
PG_USER="postgres"
DATA=$(date +%Y%m%d_%H%M%S)
mkdir -p "$BACKUP_DIR/daily"
for DB in $(psql -U "$PG_USER" -t -c "SELECT datname FROM pg_database WHERE datistemplate = false AND datname != 'postgres'"); do
DB=$(echo "$DB" | xargs)
pg_dump -U "$PG_USER" -Fc -d "$DB" \
-f "$BACKUP_DIR/daily/${DB}_${DATA}.pgdump"
done
pg_dumpall -U "$PG_USER" --globals-only \
-f "$BACKUP_DIR/daily/globals_${DATA}.sql"
find "$BACKUP_DIR/daily" -type f -mtime +"$DIAS_MANTER" -delete
0 2 * * * /usr/local/bin/pg-backup.sh >> /var/log/pg-backup.log 2>&1
Segurança do Backup — Compressão, Criptografia e S3
Compressão com Gzip
pg_dump -U postgres -Fp -d meudb | gzip > /backup/meudb_$(date +%Y%m%d).sql.gz
gunzip -c /backup/meudb_20260322.sql.gz | psql -U postgres -d meudb_restaurado
Criptografia com GPG
pg_dump -U postgres -Fc -d meudb | \
gpg --encrypt --recipient admin@exemplo.com \
-o /backup/meudb_$(date +%Y%m%d).pgdump.gpg
gpg --decrypt /backup/meudb_20260322.pgdump.gpg | \
pg_restore -U postgres -d meudb_restaurado
Upload para S3
aws s3 cp /backup/meudb_20260322.pgdump \
s3://meus-backups-pg/daily/ --storage-class STANDARD_IA
aws s3 sync /backup/postgresql/ s3://meus-backups-pg/ --storage-class STANDARD_IA
Comparativo de Métodos de Backup
| Método | Velocidade | Tamanho | Restauração Seletiva | Suporte PITR | Caso de Uso |
|---|---|---|---|---|---|
pg_dump (personalizado) | Média | Pequeno | Sim | Não | Backup diário por banco |
pg_dump (SQL simples) | Média | Grande | Não | Não | Bancos pequenos, portabilidade |
pg_dumpall | Lenta | Grande | Não | Não | Cluster completo + roles |
pg_basebackup | Rápida | Dir. completo | Não | Sim (com WAL) | Base PITR, standby |
| WAL archiving | Contínuo | Variável | Não | Sim | Proteção contínua |
Cenário Real: Recuperação de Desastre
Situação: Seu servidor PostgreSQL 16 em produção falha às 15:47 de uma terça-feira. O último pg_basebackup foi executado no domingo às 01:00. O WAL archiving para S3 funcionou continuamente.
Objetivo: Restaurar ao estado das 15:45.
Passo 1 — Provisionar Novo Servidor
sudo systemctl stop postgresql
sudo rm -rf /var/lib/postgresql/16/main/*
Passo 2 — Restaurar Backup Base
cd /var/lib/postgresql/16/main
sudo -u postgres tar -xzf /backup/base/20260320/base.tar.gz .
sudo -u postgres tar -xzf /backup/base/20260320/pg_wal.tar.gz pg_wal/
Passo 3 — Configurar Recuperação
restore_command = 'aws s3 cp s3://meus-backups-pg/wal/%f %p'
recovery_target_time = '2026-03-22 15:45:00'
recovery_target_action = 'promote'
sudo -u postgres touch /var/lib/postgresql/16/main/recovery.signal
sudo systemctl start postgresql
sudo tail -f /var/log/postgresql/postgresql-16-main.log
Passo 4 — Verificar Dados e Retomar Operações
SELECT COUNT(*) FROM pedidos WHERE created_at < '2026-03-22 15:46:00';
Casos Especiais e Erros Comuns
- Bancos grandes (>100 GB): Use
pg_dump -jepg_restore -jpara dumps e restaurações paralelas. - Bloqueios durante o backup:
pg_dumpadquire bloqueioACCESS SHARE. Execute backups em janelas de baixo tráfego. - Diferenças de codificação: Crie o banco destino com o mesmo encoding e locale que o banco de origem.
- Sequências: O formato personalizado captura os valores de sequência no momento do dump.
- Extensões: Certifique-se de que as mesmas extensões estejam disponíveis no servidor de restauração.
- Tablespaces personalizados: Devem existir com os caminhos corretos antes de executar
pg_restore.
Solução de Problemas
| Problema | Causa Provável | Solução |
|---|---|---|
ERROR: permission denied no pg_dump | Role sem privilégios de leitura | Conceda pg_read_all_data ou use o superusuário postgres |
ERROR: relation already exists no pg_restore | Restaurando em banco não vazio | Elimine e recrie o banco destino ou use o flag --clean |
archive_command falha silenciosamente | Caminho ou permissões incorretos | Verifique pg_stat_archiver.last_failed_wal e teste o comando manualmente |
| PITR travado reproduzindo WAL | recovery_target_time no futuro ou fuso errado | Use timestamps UTC; verifique show timezone no psql |
pg_basebackup: error: could not connect | Sem entrada no pg_hba.conf | Adicione host replication replicator 127.0.0.1/32 md5 ao pg_hba.conf |
| Restauração muito lenta | Restauração single-thread de dump grande | Use pg_restore -j N onde N = número de núcleos CPU |
Resumo
- Use pg_dump (formato personalizado) diariamente para backups lógicos com restauração seletiva.
- Use pg_dumpall —globals-only diariamente para capturar roles e tablespaces.
- Use pg_basebackup semanalmente como base binária para restauração completa rápida.
- Habilite o WAL archiving para proteção contínua e PITR.
- Criptografe os backups com GPG e armazene fora do site em S3.
- Teste as restaurações regularmente — um backup não testado não é um backup.
- Use cron + scripts de rotação para automatizar e remover backups antigos.