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_basebackup
da 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.