O cenário é o pesadelo de qualquer equipe de tecnologia: o banco de dados de produção caiu, os dados já foram extraídos com segurança, mas a aplicação está fora do ar. O relógio está correndo, cada minuto significa prejuízo e o restore padrão está avançando a passos de tartaruga.
Se você simplesmente rodar um comando de restauração padrão em um banco de dados de centenas de gigabytes, ele vai demorar horas. Por quê? Porque o Postgres, por padrão, vai processar tudo de forma sequencial, escrevendo logs de transação pesados e checando restrições linha por linha.
No post anterior da nossa série Guia de Sobrevivência: Backup e Manutenção no Postgres, vimos como usar o pg_restore de forma cirúrgica. Hoje, o foco é força bruta e velocidade. Vamos aprender como tunar os parâmetros do Postgres e usar paralelismo para reduzir o tempo de downtime drasticamente.
Estratégia 1: Multiplicando o poder com Jobs Paralelos (-j)
Assim como vimos no pg_dump, o pg_restore possui a flag -j (--jobs). Se você gerou o seu backup usando o formato Custom (-F c) ou Directory (-F d), você pode dividir o trabalho de restauração entre vários núcleos de CPU.
Bash
pg_restore -U postgres -h localhost -d meu_banco -j 6 -v backup_producao.dump
Como o Postgres gerencia isso por baixo do pano?
Quando você passa -j 6, o pg_restore abre 6 conexões simultâneas com o banco de dados.
- Um worker começa a criar a estrutura das tabelas.
- Assim que as tabelas são criadas, os workers começam a carregar os dados de tabelas diferentes ao mesmo tempo.
- O Pulo do Gato: O
pg_restoreé inteligente. Ele carrega os dados primeiro e, só no final, coloca os múltiplos workers para recriar os índices e chaves estrangeiras em paralelo. Criar índices em paralelo economiza um tempo absurdo.
⚠️ Atenção: Certifique-se de que o servidor de destino aguenta o tranco. Cada job consome CPU e I/O de disco. Configurar mais jobs do que os cores de CPU disponíveis vai causar gargalo de contexto e deixar o processo mais lento.
Estratégia 2: Tunando o Postgres temporariamente para o Restore
Durante uma restauração pesada, o gargalo geralmente é o disco (I/O) e a escrita de logs do sistema. Se você está subindo um banco do zero (ou em uma instância temporária), você pode alterar alguns parâmetros no arquivo postgresql.conf antes de começar e reverter após o término.
Aqui estão as variáveis que mudam o jogo:
1. maintenance_work_mem (Aumente sem pena)
Este parâmetro dita quanta memória RAM o Postgres pode usar para criar índices e chaves estrangeiras. O padrão costuma ser muito baixo (ex: 64MB). Para o restore, mude para valores agressivos, como 1GB, 2GB ou até 4GB (dependendo da RAM disponível no servidor).
maintenance_work_mem = 2GB
2. max_wal_size e checkpoint_timeout
Durante o restore, o Postgres insere milhões de linhas por segundo. Isso gera uma quantidade massiva de arquivos WAL (Write-Ahead Logs), forçando o banco a fazer “checkpoints” o tempo todo (o que joga os dados do cache para o disco de forma síncrona, travando o processo). Aumente o limite para evitar checkpoints frequentes:
max_wal_size = 16GB
checkpoint_timeout = 30min
3. synchronous_commit = off
Diz ao Postgres que ele não precisa esperar a confirmação física de escrita no disco para cada transação antes de prosseguir. Para restaurar um backup, isso acelera muito a velocidade de ingestão.
synchronous_commit = off
Estratégia 3: Desativando Triggers e Constraints
Se você está restaurando dados em cima de tabelas que já possuem gatilhos (triggers) de auditoria ou integrações, o Postgres vai disparar essa lógica para cada linha inserida, destruindo a performance.
Se você está usando o pg_restore com a flag --data-only (-a), adicione a flag --disable-triggers:
Bash
pg_restore -U postgres -d meu_banco -a --disable-triggers backup_dados.dump
Nota: Para usar esta flag, você precisa rodar o restore com um usuário que tenha privilégios de superusuário (como o postgres), pois desativar triggers temporariamente exige permissões altas.
O Checklist de Produção para um Restore Ultraveloz
Para consolidar, aqui está o passo a passo ideal adotado por equipes de DevOps sêniores para reerguer um ambiente gigante:
- Ajuste o arquivo
postgresql.confcom os parâmetros tunados (maintenance_work_mem,max_wal_size, etc.). - Reinicie o serviço do Postgres para aplicar as configurações.
- Execute o
pg_restoreutilizando paralelismo coerente com o hardware (-j N). - Assim que o restore terminar com sucesso, volte os parâmetros originais no
postgresql.conf. - Reinicie o Postgres novamente.
- Execute um
ANALYZEgeral no banco (assunto que veremos detalhadamente mais à frente) para que o otimizador de queries saiba que os dados voltaram e monte os planos de execução corretos.
Conclusão
Restauração de banco de dados em produção não precisa ser um jogo de paciência e agonia. Sabendo usar o paralelismo do pg_restore e abrindo as torneiras de memória e escrita do PostgreSQL, cenários que demorariam uma madrugada inteira podem ser resolvidos em menos de uma hora.
Com este post, encerramos nossa jornada sobre Backups e Restaurações. A partir do próximo artigo, estaremos, focados em Saúde e Manutenção Interna do Banco. Vamos descobrir o que é o temido bloat, como funciona o MVCC e por que o comando vacuumdb é o melhor amigo do seu armazenamento. Até lá!
Você já teve que rodar um restore sob pressão? Quanto tempo demorou? Sabia que dava para tunar a memória do Postgres para acelerar o processo? Deixe sua experiência nos comentários!