postgres postgresql backup
Um backup é uma foto física (baseada em arquivos, diretórios e links simbólicos) da instância inteira do PostgreSQL, que inclui todos os bancos de dados e objetos globais, assim como o estado das transações e a posição da instância na linha do tempo. Com isso, ele pode ser usado para restaurar a instância para qualquer momento entre o final do backup e a última transação processada (contanto que o histórico da linha do tempo seja alimentado sem lacunas na restauração).
Um backup (e sua respectiva restauração) é uma estratégia usada para garantir a continuidade do seu negócio mesmo após grandes falhas de hardware e software, assim como erros humanos acidentais ou ações maliciosas. Ele também é o ponto de partida das replicações físicas (síncronas e assíncronas).
ATENÇÃO! Dumps não são propriamente backups e não devemos depender deles para fins de confiabilidade ou continuidade de negócio porque além da grande quantidade de locks que eles exigem para serem extraídos e do alto tempo de restauração necessário para restaurá-los, eles também não atendem a maioria dos casos em que temos RPO (Recovery Point Objective), causando uma perda de dados maior que o aceitável.
Existem diversas formas de fazer um backup do PostgreSQL. A mais comum é no
nível do sistema de arquivos, através de ferramentas comuns, como cp. Também é
possível usar snapshots de volumes ou de sistemas de arquivos.
Contudo, algumas características que todas têm em comum incluem o fato de que o sistema continua disponível para transações a todo momento, sem locks adicionais serem adquiridos. Adicionalmente, backups podem ser usados para restauração do estado da instância para qualquer momento após ele ter sido feito, como é necessário para recuperação de desastres e criação de réplicas, contanto que todo o histórico de WAL esteja sendo continuamente guardado com segurança e confiabilidade, como visto em WAL.
Os passos simplificados para criar um backup são os seguintes:
-
O comando de início do backup (
pg_start_backup()) coloca uma marcação (A) na linha do tempo do WAL indicando que um backup foi iniciado (no segmento…012). - Os diretórios de dados são copiados (2), incluindo o diretório de dados principal e todos os diretórios de tablespaces.
-
O comando de fim de backup (
pg_stop_backup()) coloca outra marcação (B) na linha do tempo do WAL indicando que o backup terminou (no segmento…013). - Todos os segmentos de WAL gerados entre as duas marcações, incluindo aqueles nas quais as próprias marcações se encontram, são copiados e guardados com os diretórios de dados. Eles podem ser copiados por arquivamento (a), por conexão de replicação (b).
╔═══════════╗↔──────────────────┐
║ Aplicação ║╗↔─────────────────┤
╚═══════════╝║╗↔────────────────┤
╚═══════════╝║↔────────────────┤
╚═══════════╝↔────────────────┤
│
┌───────────────────┐ │
╔════════════════════╡PostgreSQL (origem)╞═════════════════════╗ │
║ └───────────────────┘ ║ │
╠═╡global/╞═══════╗ ╔══════════════╡base/╞═╣ │
║ ║ ║ ║ │
║ O O ║ ║ ┏━┥banco de dados┝━┓ ║ │
║ ─┼─ ─┼─ ║ ║ ┃ ┌─┤schema├─────┐ ┃ ║ │
║ │ │ ║ ┊←┈╢ ┃ │ ☑ tabelas │←╂─╫───┤
║ ╱ ╲ ╱ ╲ ║ ┊←┈╢ ┃ │ ☑ índices │←╂─╫───┤
║ ☑ usuários ║ ┊←┈╢ ┃ │ ☑ visões │←╂─╫───┤
║ ☑ grupos ║ ┊←┈╢ ┃ │ ☑ sequências │←╂─╫───┤
║ ☑ slots de ║ ┊←┈╢ ┃ │ ☑ … │←╂─╫───┘
║ ☑ replicação ║ ┊ ║ ┃ └──────────────┘ ┃ ║
║ ☑ pg_control┅┅┅┅╫┅┅┓ ┊ ║ ┗━━━━━━━━━━━━━━━━━━┛ ║
║ ║ ┋ ┊ ║ ║
╠═════════════════╝ ┋ ┊ ╚══════════════════════╣
║ ┋ ↓ ║
╠═╡pg_wal/╞══════════╪═══════════════╪═══════════╗ ║
║ ┋ ┊┈┈┈┈┈┈┈┈┈┈→╫→┈┈┈┈┈┈┈┈┈┈┈→╫→┈┈┈┈┈┈┈┈┐
║ ┌────────────┐ ┌──↓─────────┐ ↓ ║ (4) ║ (b) ┊
║ →│+--++--(A)++│→│-++++-(B)--+│→╷++-.........╷→ ║ ║ ┊
║ └┤/…00000012├┘ └┤/…00000013├┘↓└┤/…00000014├┘ ║ ┌───────┐ ║ (a) ┊
║ └┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈→╫→┈│…(B)--+│┈→╫→┈┈┐ ┊
║ ║ └┤/…013├┘ ║ ┊ ┊
╚════════════════════════════════════════════════╩═════════════╝ ┊ ┊
╏ ┊ ┊
╏ ┊ ┊
╏ ┊ ┊
╏ ↓ ↓
╏ ┏━━━━━━━━━━━━━┷━━━━━┷━━━━━━━┓
(2)╏ ┃ ┌───────┐ ┌───────┐ ┃
╔═══════╗ ┃ →│…-(A)++│→│…(B)--+│→ ┃
╠══╗ ╔══╣ ┃ └┤/…012├┘ └┤/…013├┘ ┃
╠══╝ ╚══╣ ┠────────↑────────↑─────────┨
╠═════╗ ║ ┃ ╔═══════════════╗ ┃
╚═════╩═╝ ┃ ╠═════╗ ╔═════╣ ┃
╏ ┃ ║ ║ ║ ║ ┃
┗╍╍╍╍╍╍╸┃……………╠═════╝ ╚═════╣……………┃
┃ ╠══════════╗ ║ ┃
┃ ║ ║ ║ ┃
┃ ╚══════════╩════╝ ┃
┃ ┌──────────────────┐ ┃
┗━━━━┥Servidor de backup┝━━━┛
└──────────────────┘
Quando o backup for restaurado, a instância estará em um estado inconsistente pois a cópia do segundo passo não foi atômica e, portanto, os arquivos estão espalhados em momentos distintos da linha do tempo do WAL. Para alcançar um estado consistente o PostgreSQL irá reaplicar todas as alterações contidas no WAL entre o início e o fim do backup, marcados pelos passos um e três.
Portanto, o último passo é necessário para guardar ao menos os segmentos gerados durante o backup, caso contrário não é possível encontrar um estado consistente e o PostgreSQL vai se recusar a aceitar conexões. Se o arquivamento já tiver sido configurado, o quarto passo pode ser omitido.
Ao final, o backup resultante é quase indistinguível de uma instância parada, sendo que para restaurá-lo só é necessário iniciar o serviço. Também é possível comprimir, encriptar, deduplicar, mover e copiar o diretório de backup como qualquer outro diretório com arquivos.
É possível seguir esses passos usando a API de baixo nível, Mas essa seria uma tarefa manual repleta de detalhes e riscos que só deveriam ser enfrentados pelas ferramentas de backup.
A ferramenta trazida pelo próprio PostgreSQL é o pg_basebackup. Ele engloba
todos os passos acima, inclusive com o arquivamento por conexão de replicação
nas versões recentes. Quando executado, ele gera um diretório de dados contendo
uma cópia fiel da instância original e incluindo os segmentos de WAL
necessários para a restauração:
[postgres@pg-1 ~]$ pg_basebackup -D meubackup [postgres@pg-1 ~]$ ls meubackup/pg_wal 000000010000007F00000094 archive_status
Mas se o arquivamento estiver já estiver sendo feito de outra forma, ele pode
ser omitido do backup com -X none:
[postgres@pg-1 ~]$ pg_basebackup -D meubackup -X none [postgres@pg-1 ~]$ ls meubackup/pg_wal archive_status
Alguns sistemas de arquivos, gerenciadores de volumes, virtualizadores e
storages têm a capacidade de fazer snapshots dos seus conteúdos. Dado que a
todo momento ou o estado do PostgreSQL em disco é consistente ou a consistência
pode ser alcançada através do arquivo de controle e diretório de WAL, é
possível usar essa funcionalidade como estratégia de backups contanto que o
PostgreSQL esteja completamente em um volume, sem tablespaces adicionais ou
separação de pg_wal em outro volume.
Para restaurar um backup, é necessário:
- Movê-lo (e descompactar, desencriptar) para a localização onde o serviço possa alcançá-lo, normalmente copiando do servidor de backup para o servidor de banco de dados.
-
Todo o WAL gerado entre as marcações de início (A) e fim (B) do backup precisa
estar disponível na restauração. Os segmentos podem ser copiados junto com o
backup e colocados em
pg_wal(a) ou recuperados do arquivamento (b). - Ao iniciar o serviço, o PostgreSQL irá reproduzir todas as alterações entre (A) e (B) para alcançar um estado consistente.
- Dependendo do alvo e da ação escolhidas, a instância pode começar a responder transações da aplicação.
╔═══════════╗↔────────────────────────┐
║ Aplicação ║╗↔───────────────────────┤
╚═══════════╝║╗↔──────────────────────┤
╚═══════════╝║↔──────────────────────┤
╚═══════════╝↔──────────────────────┤
(4)│
│ ┌───────────────────────┐
│ ╔════════════════╡PostgreSQL (restaurado)╞═════════════════════╗
│ ║ └───────────────────────┘ ║
│ ╠═╡base/╞══════════════╗ ╔═══════╡global/╞═╣
│ ║ ║ ║ ║
│ ║ ┏━┥banco de dados┝━┓ ║ ║ O O ║
│ ║ ┃ ┌─┤schema├─────┐ ┃ ║ ║ ─┼─ ─┼─ ║
├───╫─╂→│ ☑ tabelas │ ┃ ╟←┈┊(3) ║ │ │ ║
├───╫─╂→│ ☑ índices │ ┃ ╟←┈┊ ║ ╱ ╲ ╱ ╲ ║
├───╫─╂→│ ☑ visões │ ┃ ╟←┈┊ ║ ☑ usuários ║
├───╫─╂→│ ☑ sequências │ ┃ ╟←┈┊ ║ ☑ grupos ║
└───╫─╂→│ ☑ … │ ┃ ╟←┈┊ ║ ☑ slots de ║
║ ┃ └──────────────┘ ┃ ║ ┊ ║ ☑ replicação ║
║ ┗━━━━━━━━━━━━━━━━━━┛ ║ ┊ ┏┅┅╫┅☑ pg_control ║
║ ║ ┊ ┋ ║ ║
╠══════════════════════╝ ┊ ┋ ╚═════════════════╣
║ ↑ ┋ ║
║ ╔═══════════╪═══════════════╪══════════╡pg_wal/╞═╣
║ ║ ┊(2) ┋ ║
║ ║ ↑ ┌─────────↓──┐ ┌────────────┐ ║
║ (b) ║ ←╷.........-++╷←│+--(B)-++++-│←│++(A)--++--+│← ║
║ ┌───────┐ ║ └┤/…00000014├┘↑└┤/…00000013├┘ └┤/…00000012├┘ ║
┌┈┈→╫→┈│…(B)--+│┈→╫→┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┘ ║
┊ ║ └┤/…013├┘ ║ (a) ║
┊ ╚═════════════╩════════════════════════════════════════════════╝
┊ ╏
┊ ╏
┊ ╏
↑ ╏
┏━━━━━━━━━━━━━━━━━━━┷━━━━━━━┓ ╏(1)
┃ ┌───────┐ ┌───────┐ ┃ ╏
┃ →│…-(A)++│→│…(B)--+│→ ┃ ╔═══════╗
┃ └┤/…012├┘ └┤/…013├┘ ┃ ╠══╗ ╔══╣
┠────────↑────────↑─────────┨ ╠══╝ ╚══╣
┃ ╔═══════════════╗ ┃ ║ ╔═════╣
┃ ╠═════╗ ╔═════╣ ┃ ╚═╩═════╝
┃ ║ ║ ║ ║ ┃ ╏
┃……………╠═════╝ ╚═════╣……………┃╺╍╍╍╍╍╍┛
┃ ╠══════════╗ ║ ┃
┃ ║ ║ ║ ┃
┃ ╚══════════╩════╝ ┃
┃ ┌──────────────────┐ ┃
┗━━━━┥Servidor de backup┝━━━┛
└──────────────────┘
Para isso, é necessário fornecer os segmentos direta ou indiretamente ao
PostgreSQL antes que o serviço seja iniciado sobre o diretório de dados. A forma
direta é copiando manualmente os segmentos para o diretório pg_wal, que serão
consumidos naturalmente. Contudo, não é prático fazer essa cópia completa,
especialmente se o volume de segmentos for muito alto.
A melhor forma é informando ao PostgreSQL um comando similar ao
archive_command, mas com o propósito oposto, ou seja, de buscar um segmento de
WAL de um local remoto. O parâmetro que contém o comando é chamado
restore_command, aceita os padrões %f para nome do arquivo e %p para
caminho absoluto até o diretório onde o arquivo será armazenado, por exemplo:
restore_command = 'scp pg-a.local:archive/16/%f %p'
A partir do PostgreSQL versão 12, esse parâmetro é colocado no arquivo
postgresql.conf. Em versões mais antigas, ele é colocado em um arquivo
recovery.conf.
Outros parâmetros
de restauração também acompanham essa movimentação.
Por fim, a partir da versão 12 é necessário criar um arquivo recovery.signal
para indicar que o PostgreSQL deve iniciar a recuperação. Em versões mais
antigas é necessário adicionar a configuração standby_mode = on no arquivo
recovery.conf.
Em alguns casos queremos restaurar o backup até certo ponto do passado, por
exemplo antes de um DROP acidental. Para isso, podemos incluir um alvo na
recuperação. Quando esse alvo é alcançado, o PostgreSQL toma uma ação
(recovery_target_action), como pausar a instância (pause), permitindo
consultas e inspeção, parar o serviço (shutdown) ou mesmo promover a instância
torna-a um novo primário (promote).
Esse alvo é informado como mais alguns parâmetros no arquivo de configuração e
ele pode ser um xid (recovery_target_xid), um LSN (recovery_target_lsn), um
nome definido previamente (recovery_target_name) ou uma data e hora
específicos (recovery_target_time). Por exemplo, o DBA pode ter criado um
ponto de restauração antes de uma migração arriscada:
[[local]:5432] postgres@postgres=# SELECT pg_create_restore_point('pre-migracao');
Quando um backup daquela instância precisar avançado até aquele ponto e restaurado como novo primário, o DBA usa o alvo e a ação:
recovery_target_name = 'pre-migracao' recovery_target_action = 'promote'
A restauração com alvo é também chamada de Point-in-Time Recovery (PITR), ou restauração a um ponto no tempo.
Apesar do pg_basebackup fazer backups confiáveis, ele não cuida de diversas
outras tarefas importantes, como:
- agendamento de backups
- teste dos backups assim que são feitos, para garantir que podem ser restaurados futuramente
- expurgo de backups antigos
- expurgo de segmentos de WAL arquivados antigos
- gestão de política de retenção
- compressão
- encriptação
- deduplicação
- backups incrementais ou diferenciais
- arquivamento por conexão de replicação
- integração com ferramentas de replicação e alta disponibilidade
- …
Para essas e outras funcionalidades, é necessário usar ferramentas de terceiros, como:
-
Faça um backup com
pg_basebackupda instância de pg-1 para um local na máquina pg-a.
- Copie o backup para a máquina pg-2.
- Restaure o backup na máquina pg-2 como novo primário consumindo o WAL presente em pg-a.