Restaurar backup do PostgreSQL

    Saber restaurar um backup é tão importante quanto criá-lo. O restore é o momento mais crítico — geralmente em uma crise, com pressão de tempo. Treinar o processo antes da emergência é essencial. Este guia cobre restore completo, parcial, para banco limpo e migração entre servidores.

    Restaurar backup SQL (formato plain)

    Para backups gerados com pg_dump --format=plain (padrão):

    bash
    # Cenário 1: Restaurar em banco existente (sobrescrever dados)
    # ATENÇÃO: isso apaga os dados atuais do banco!
    
    # Opção A: Dropar e recriar o banco antes do restore
    sudo -u postgres psql << 'EOF'
    SELECT pg_terminate_backend(pid)
    FROM pg_stat_activity
    WHERE datname = 'minha_db' AND pid <> pg_backend_pid();
    
    DROP DATABASE IF EXISTS minha_db;
    CREATE DATABASE minha_db OWNER minha_app;
    EOF
    
    # Restaurar o backup (arquivo .sql ou .sql.gz)
    gunzip -c /var/backups/minha_db_20260607.sql.gz \
      | sudo -u postgres psql minha_db
    
    # Cenário 2: Restaurar em banco de teste (sem afetar produção)
    sudo -u postgres createdb -O minha_app minha_db_restore_test
    gunzip -c /var/backups/minha_db_20260607.sql.gz \
      | sudo -u postgres psql minha_db_restore_test
    
    # Verificar restore:
    sudo -u postgres psql minha_db_restore_test -c "
    SELECT tablename, n_live_tup
    FROM pg_stat_user_tables
    ORDER BY n_live_tup DESC;
    "
    Atenção
    Sempre teste o restore em um banco separado antes de substituir o banco de produção. Um restore em produção com dados corrompidos piorará a situação.

    Restaurar backup custom com pg_restore

    Backups no formato custom (pg_dump -Fc) têm mais opções de restore:

    bash
    # Backup custom (gerado com pg_dump -Fc):
    pg_dump -Fc minha_db > backup.dump
    
    # Restaurar todo o banco:
    pg_restore -d minha_db -U minha_app -h localhost backup.dump
    
    # Restaurar apenas tabelas específicas:
    pg_restore -d minha_db -t usuarios -t pedidos backup.dump
    
    # Restaurar apenas o schema (sem dados):
    pg_restore -d minha_db --schema-only backup.dump
    
    # Restaurar apenas os dados (schema já existe):
    pg_restore -d minha_db --data-only backup.dump
    
    # Restaurar em paralelo (mais rápido para bancos grandes):
    pg_restore -d minha_db -j 4 backup.dump  # 4 workers paralelos
    
    # Ver conteúdo do backup sem restaurar:
    pg_restore -l backup.dump | head -50
    
    # Verbose para debug:
    pg_restore -d minha_db -v backup.dump 2>&1 | tail -30

    Migrar banco de dados entre servidores

    Copiar banco de produção para novo servidor sem arquivo intermediário:

    bash
    # Migração em pipeline (sem arquivo intermediário) — mais rápido
    # Fonte: VPS_ANTIGA | Destino: VPS_NOVA
    
    # No servidor de destino (VPS nova):
    # 1. Criar banco e usuário destino
    sudo -u postgres psql << 'EOF'
    CREATE USER minha_app WITH PASSWORD 'senha_app';
    CREATE DATABASE minha_db OWNER minha_app;
    EOF
    
    # 2. Executar migração em pipeline (SSH + pg_dump + psql):
    ssh usuario@VPS_ANTIGA \
      "PGPASSWORD=senha pg_dump -U minha_app minha_db" \
      | PGPASSWORD=senha psql -U minha_app -h localhost minha_db
    
    # Alternativa com compressão (para conexões lentas):
    ssh usuario@VPS_ANTIGA \
      "PGPASSWORD=senha pg_dump -U minha_app minha_db | gzip" \
      | gunzip | PGPASSWORD=senha psql -U minha_app minha_db
    
    # Verificar integridade após migração:
    # No destino:
    psql -U minha_app minha_db -c "SELECT count(*) FROM usuarios;"
    # Comparar com a fonte:
    ssh usuario@VPS_ANTIGA "psql -U minha_app minha_db -c 'SELECT count(*) FROM usuarios;'"

    Restaurar uma tabela específica sem afetar o restante

    Recupere apenas a tabela que foi corrompida ou deletada acidentalmente:

    bash
    # Cenário: DELETE acidental na tabela pedidos
    # Backup disponível: /var/backups/minha_db_20260607.sql.gz
    
    # 1. Extrair apenas a tabela pedidos do backup para arquivo separado
    pg_restore -t pedidos -f /tmp/pedidos_only.sql /var/backups/minha_db.dump
    # (apenas para backups formato custom -Fc)
    
    # Para backup formato plain (SQL):
    # Extrair manualmente com grep/sed entre COPY pedidos e \.
    # Ou: restaurar em banco temporário e copiar de lá
    
    # 2. Restaurar em banco temporário
    sudo -u postgres createdb minha_db_temp
    gunzip -c /var/backups/minha_db_20260607.sql.gz | sudo -u postgres psql minha_db_temp
    
    # 3. Copiar a tabela do backup para produção usando INSERT
    sudo -u postgres psql << 'EOF'
    -- Truncar tabela atual (se corrompida)
    TRUNCATE TABLE minha_db.public.pedidos;
    
    -- Copiar do backup
    INSERT INTO minha_db.public.pedidos
    SELECT * FROM minha_db_temp.public.pedidos;
    
    -- Verificar
    SELECT count(*) FROM minha_db.public.pedidos;
    EOF
    
    # 4. Limpar banco temporário
    sudo -u postgres dropdb minha_db_temp

    Point-in-Time Recovery (PITR)

    Restaure o banco para um momento específico no tempo com WAL archiving:

    bash
    # PITR requer configuração prévia de WAL archiving:
    # postgresql.conf:
    # archive_mode = on
    # archive_command = 'aws s3 cp %p s3://meu-bucket/wal/%f'
    # restore_command = 'aws s3 cp s3://meu-bucket/wal/%f %p'
    
    # Para fazer PITR após DELETE acidental às 14:32:
    
    # 1. Parar PostgreSQL
    sudo systemctl stop postgresql
    
    # 2. Restaurar pg_basebackup (snapshot mais recente antes do incidente)
    sudo rm -rf /var/lib/postgresql/17/main/
    sudo -u postgres pg_basebackup -D /var/lib/postgresql/17/main -Fp
    
    # 3. Configurar recovery
    sudo -u postgres cat > /var/lib/postgresql/17/main/postgresql.auto.conf << EOF
    restore_command = 'aws s3 cp s3://meu-bucket/wal/%f %p'
    recovery_target_time = '2026-06-07 14:30:00 America/Sao_Paulo'
    recovery_target_action = 'promote'
    EOF
    sudo -u postgres touch /var/lib/postgresql/17/main/recovery.signal
    
    # 4. Iniciar PostgreSQL — ele aplica WAL até o momento especificado
    sudo systemctl start postgresql
    Dica
    PITR é a solução mais poderosa para recuperação de dados deletados acidentalmente — permite restaurar para segundos antes do incidente. Requer configuração prévia de WAL archiving contínuo.

    $ runstack deploy --plan starter

    Não quer configurar manualmente?

    Não quer configurar manualmente? Implante o VPS em menos de 3 minutos com a Runstack. Infraestrutura da OPEN DATACENTER, com servidores no Brasil.

    Perguntas frequentes