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 postgres ou um role com privilégios pg_read_all_data / SUPERUSER.
  • Espaço em disco suficiente (pelo menos 1,5× o tamanho dos seus bancos de dados).
  • aws-cli ou rclone instalado se usar armazenamento em nuvem.
  • gpg instalado 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

RecursoFormato Personalizado (-Fc)SQL Simples (-Fp)
CompressãoIntegrada (zlib)Não (use gzip separado)
Restauração seletivaSim (-t, -n, -T)Não
Restauração paralelaSim (pg_restore -j)Não
Legível por humanosNãoSim
Ferramenta de restauraçãopg_restorepsql

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 >= 2 no postgresql.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

  1. Pare o PostgreSQL e substitua o diretório de dados pelo backup base.
  2. Crie recovery.signal no diretório de dados (PostgreSQL 12+).
  3. 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'
  1. 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étodoVelocidadeTamanhoRestauração SeletivaSuporte PITRCaso de Uso
pg_dump (personalizado)MédiaPequenoSimNãoBackup diário por banco
pg_dump (SQL simples)MédiaGrandeNãoNãoBancos pequenos, portabilidade
pg_dumpallLentaGrandeNãoNãoCluster completo + roles
pg_basebackupRápidaDir. completoNãoSim (com WAL)Base PITR, standby
WAL archivingContínuoVariávelNãoSimProteçã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 -j e pg_restore -j para dumps e restaurações paralelas.
  • Bloqueios durante o backup: pg_dump adquire bloqueio ACCESS 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

ProblemaCausa ProvávelSolução
ERROR: permission denied no pg_dumpRole sem privilégios de leituraConceda pg_read_all_data ou use o superusuário postgres
ERROR: relation already exists no pg_restoreRestaurando em banco não vazioElimine e recrie o banco destino ou use o flag --clean
archive_command falha silenciosamenteCaminho ou permissões incorretosVerifique pg_stat_archiver.last_failed_wal e teste o comando manualmente
PITR travado reproduzindo WALrecovery_target_time no futuro ou fuso erradoUse timestamps UTC; verifique show timezone no psql
pg_basebackup: error: could not connectSem entrada no pg_hba.confAdicione host replication replicator 127.0.0.1/32 md5 ao pg_hba.conf
Restauração muito lentaRestauração single-thread de dump grandeUse 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.

Artigos Relacionados