Figura 25.1. Fluxo de transação
Durante todo tempo, o PostgreSQL
escreve arquivos de WAL
(write-ahead log)
[145]
no subdiretório pg_wal do diretório de dados
da instância.
Os arquivos de WAL anotam todas as alterações
feitas nos arquivos de dados do banco de dados.
Estes arquivos existem principalmente para fins de segurança contra
falhas: se o sistema travar, o banco de dados poderá ser restaurado
para um estado consistente “reproduzindo” as entradas
escritas desde o último ponto de verificação.
Entretanto, a existência destes arquivos possibilita o uso de uma
terceira estratégia para cópia de segurança de bancos de dados:
pode-se combinar a cópia de segurança no nível de sistema
de arquivos com a cópia de segurança dos arquivos de
WAL.
Se for necessário fazer a restauração, pode-se restaurar a cópia de
segurança do sistema de arquivos e, em seguida, reproduzir os arquivos
de WAL a partir das cópias de segurança dos arquivos
de WAL para trazer o sistema para o estado corrente.
Esta abordagem é mais complexa de administrar do que qualquer uma
das abordagens anteriores, mas tem alguns benefícios significativos:
Não há necessidade de haver uma cópia de segurança do sistema de arquivos perfeitamente consistente como ponto de partida. Qualquer inconsistência interna na cópia de segurança será corrigida pela reprodução dos arquivos (isto não é muito diferente do que acontece durante a recuperação de falhas). Portanto, não há necessidade de um recurso de instantâneo do sistema de arquivos, basta apenas o tar ou uma ferramenta de arquivamento semelhante.
Como se pode formar uma sequência indefinidamente longa de arquivos de WAL para reprodução, a cópia de segurança contínua pode ser obtida simplesmente continuando a arquivar os arquivos de WAL. Isto é particularmente valioso para bancos de dados grandes, onde pode não ser conveniente fazer uma cópia de segurança completa com frequência.
Não é necessário reproduzir as entradas do WAL até o fim. Pode-se interromper a reprodução em qualquer ponto, obtendo um instantâneo consistente do banco de dados, representando como o banco de dados se encontrava neste momento. Assim, esta técnica dá suporte a restauração para um ponto-no-tempo: é possível restaurar o estado do banco de dados para qualquer momento posterior a cópia de segurança base ter sido feita.
Se a série de arquivos de WAL for enviada continuamente para outra máquina que tenha sido carregada com o mesmo arquivo de cópia de segurança base, haverá um servidor Warm-Standby: a qualquer momento pode-se promover este servidor secundário, e ele terá uma cópia quase atual do banco de dados (veja Servidores em-espera de envio de WAL).
Os utilitários pg_dump e pg_dumpall não produzem cópias de segurança no nível do sistema de arquivos, não podendo ser usados como parte de uma solução de arquivamento contínuo. Estas cópias de segurança são lógicas, não contendo informações suficientes para serem usadas pela reprodução do WAL.
Assim como na técnica simples de cópia de segurança do sistema de arquivos, este método só pode oferecer suporte à restauração de toda a instância, e não de um subconjunto dessa. Além disso, requer muito armazenamento para arquivamento: a cópia de segurança base pode ser volumosa, e um sistema ocupado irá gerar muitos megabytes de tráfego de WAL que deverão ser arquivados. Ainda assim, é a técnica de cópia de segurança preferida em muitas situações onde há necessidade de alta confiabilidade.
Para restaurar com êxito usando o arquivamento contínuo (também chamado de “cópia de segurança online” por muitos fornecedores de banco de dados), é necessária uma sequência contínua de arquivos de WAL arquivados, que se estenda até pelo menos a hora de início da cópia de segurança base. Portanto, para começar, deve-se configurar e testar ou procedimento para arquivar arquivos de WAL antes de fazer a primeira cópia de segurança base. Assim, primeiro é discutida a mecânica de arquivamento de arquivos de WAL.
Em um sentido abstrato, um sistema PostgreSQL em execução produz uma sequência indefinidamente longa de arquivos. O sistema divide fisicamente esta sequência em arquivos de segmento de WAL, que normalmente têm 16 MB cada (embora o tamanho do segmento possa ser alterado durante o initdb). Os arquivos de segmento recebem nomes numéricos que refletem sua posição na sequência de WAL abstrata. Quando não está usando o arquivamento de WAL, o sistema normalmente cria apenas alguns arquivos de segmento, e os “recicla” renomeando os arquivos de segmento não mais necessários para números de segmento mais altos. Presume-se que os arquivos de segmento cujo conteúdo precede o último ponto de verificação não sejam mais de interesse, podendo ser reciclados.
Ao arquivar dados de WAL, é necessário capturar
o conteúdo de cada arquivo de segmento após o seu preenchimento,
e salvar estes dados em algum lugar antes que o arquivo de segmento
seja reciclado para reutilização.
Dependendo da aplicação e do hardware disponível, podem haver muitas
maneiras de “salvar os dados em algum lugar”:
se poderia copiar os arquivos de segmento para um diretório
NFS (Network File
System) montado em outra máquina, escrevê-los em uma
unidade de fita (garantindo que se tenha uma maneira de identificar
o nome original de cada arquivo), ou agrupá-los e gravá-los em CDs,
ou algo completamente diferente.
Para fornecer flexibilidade ao administrador de banco de dados,
o PostgreSQL tenta não fazer suposições
sobre como o arquivamento será feito.
Em vez disso, o PostgreSQL permite que o
administrador especifique um comando do interpretador de comandos
(shell), ou uma biblioteca de
arquivamento, a ser executado para copiar um arquivo de segmento
concluído para o destino desejado.
Isto pode ser tão simples quanto um comando do interpretador de
comandos que utiliza cp, ou pode chamar uma
função escrita em C complexa —
a escolha é do administrador.
Para ativar o arquivamento do WAL deve-se definir
o parâmetro de configuração wal_level como
replica ou superior,
archive_mode como on,
especificar o comando do interpretador de comandos a ser usado
no parâmetro de configuração archive_command,
ou especificar a biblioteca a ser usada no parâmetro de configuração
archive_library.
Na prática, estas configurações serão sempre colocadas no arquivo
postgresql.conf.
No archive_command, %p
é substituído pelo nome do caminho do arquivo a ser arquivado,
enquanto %f é substituído apenas pelo nome do
arquivo.
(O nome do caminho é relativo ao diretório de trabalho corrente,
ou seja, o diretório de dados da instância.)
Deve-se usar %% se for necessário incorporar um
caractere % real no comando.
O comando útil mais simples é algo como:
archive_command = 'test ! -f /mnt/server/archivedir/%f && cp %p /mnt/server/archivedir/%f' # Unix archive_command = 'copy "%p" "C:\\server\\archivedir\\%f"' # Windows
que irá copiar os segmentos de WAL arquiváveis
para o diretório /mnt/server/archivedir.
(Este é um exemplo, e não uma recomendação, podendo não funcionar
em todas as plataformas.)
Após os parâmetros %p e %f
terem sido substituídos, o comando real executado poderá ter
a seguinte aparência:
test ! -f \ /mnt/server/archivedir/00000001000000A900000065 && \ cp pg_wal/00000001000000A900000065 \ /mnt/server/archivedir/00000001000000A900000065
Será gerado um comando semelhante para cada novo arquivo a ser arquivado.
O comando de arquivamento será executado pelo mesmo usuário que o servidor PostgreSQL está executando. Já que a série de arquivos de WAL sendo arquivados contém de fato tudo que existe no banco de dados, deve-se ter certeza de que os dados arquivados estejam protegidos de olhares indiscretos; por exemplo, deve-se arquivar em um diretório que não tenha acesso de leitura para grupo ou para todos.
É importante que o comando de arquivamento retorne o status de saída zero se, e somente se, for bem-sucedido. Ao receber o valor zero retornado, o PostgreSQL irá assumir que o arquivo foi arquivado com sucesso, e irá removê-lo ou reciclá-lo. Entretanto, um status diferente de zero informa ao PostgreSQL que o arquivo não foi arquivado; ele tentará novamente periodicamente até conseguir.
Outra maneira de arquivar é utilizar um módulo de arquivamento
personalizado como archive_library.
Como estes módulos são escritos na linguagem C,
criar um módulo pode exigir consideravelmente mais esforço do
que escrever um comando do interpretador de comandos.
Entretanto, os módulos de arquivamento podem apresentar melhor
desempenho do que o arquivamento via interpretador de comandos,
e terão acesso a muitos recursos úteis do servidor.
Para obter mais informações sobre módulos de arquivo, veja
Capítulo 49.
Quando o comando de arquivamento for encerrado por um sinal
(diferente de SIGTERM, usado como
parte da parada do servidor), ou um erro do interpretador de comandos
com status de saída maior que 125 (tal como comando não encontrado),
ou se a função de arquivamento emitir um ERROR ou
FATAL, o processo arquivador é terminado
abruptamente e reiniciado pelo
postmaster.
Nesses casos, a falha não é relatada em
pg_stat_archiver.
Comandos e bibliotecas de arquivamento devem, em geral, ser projetados para recusar a sobrescrita de qualquer arquivo do arquivamento preexistente. Este é um recurso de segurança importante para preservar a integridade do arquivamento em caso de erro do administrador. (como enviar a saída de dois servidores diferentes para o mesmo diretório de arquivamento). É aconselhável testar a biblioteca de arquivamento proposta para garantir que ela não sobrescreva um arquivo existente.
Em casos raros, o PostgreSQL pode tentar
arquivar novamente um arquivo de WAL que já havia
sido arquivado.
Por exemplo, se o sistema falhar antes que o servidor registre de
forma persistente o sucesso do arquivamento o servidor tentará
arquivar o arquivo novamente após reiniciar (desde que o
arquivamento ainda esteja ativo).
Quando um comando ou biblioteca de arquivamento encontra um arquivo
preexistente, deve retornar um status zero ou true,
respectivamente, se o arquivo de WAL tiver
conteúdo idêntico ao do arquivo de arquivamento preexistente, e este
último estiver totalmente persistido no armazenamento.
Se o arquivo preexistente contiver conteúdo diferente do arquivo de
WAL que está sendo arquivado, o comando de
arquivamento ou a biblioteca deve retornar um
status diferente de zero ou false, respectivamente.
O comando de exemplo acima para
Unix evita sobrescrever um
arquivo existente ao incluir uma etapa separada de test.
Em algumas plataformas Unix,
o comando cp possui opções, como -i,
que podem ser usadas para fazer o mesmo de forma menos detalhada,
mas não se deve confiar nessas opções sem verificar se é retornado
o status de saída correto.
(Em particular, o comando cp do
GNU retornará o status zero quando for usada a
opção -i e o arquivo de destino já existir,
o que não é o comportamento desejado.)
Ao projetar a configuração de arquivamento, deve-se considerar o
que acontecerá se o comando de arquivamento ou biblioteca falhar
repetidamente, porque algum detalhe requer intervenção do operador,
ou o arquivamento ficar sem espaço.
Por exemplo, isto poderá ocorrer se o arquivamento for escrito em
fita sem troca automática; quando a fita ficar cheia, nada mais
poderá ser arquivado até que a fita seja trocada.
Deve-se garantir que qualquer condição de erro, ou solicitação a
um operador humano, seja informada adequadamente, para que a
situação possa ser resolvida com rapidez razoável.
O diretório pg_wal continuará sendo preenchido
com arquivos de segmento de WAL, até que a
situação seja resolvida.
(Se o sistema de arquivos contendo o diretório
pg_wal ficar cheio, o
PostgreSQL fará uma parada no nível
PANIC.
Nenhuma transação efetivada será perdida, mas o banco de dados
permanecerá fora de linha até se liberar algum espaço.)
A velocidade do comando ou da biblioteca de arquivamento não é
importante, desde que possa acompanhar a taxa média na qual o
servidor gera dados de WAL.
A operação normal continua, mesmo que o processo de arquivamento
fique um pouco atrasado.
Se o arquivamento ficar muito atrasado, isto aumentará
a quantidade de dados que serão perdidos no caso de um desastre.
Isto também significa que o diretório pg_wal
conterá muitos arquivos de segmento ainda não arquivados,
que podem por fim exceder o espaço em disco disponível.
Deve-se monitorar o processo de arquivamento para garantir que
esteja funcionando conforme o esperado.
Ao escrever o comando ou biblioteca de arquivamento, deve-se
presumir que os nomes dos arquivos a serem arquivados podem ter
até 64 caracteres, e podem conter qualquer combinação de letras
ASCII, dígitos e pontos.
Não é necessário preservar o caminho relativo original
(%p), mas é necessário preservar o nome do arquivo
(%f).
Note-se que, embora o arquivamento do WAL permita
restaurar quaisquer modificações feitas nos dados do banco de dados
PostgreSQL, ele não irá restaurar as
alterações feitas nos arquivos de configuração (ou seja,
postgresql.conf, pg_hba.conf
e pg_ident.conf), uma vez que são editados
manualmente, em vez de por meio de operações SQL.
Pode-se querer manter os arquivos de configuração em um local que
seja copiado pelos procedimentos regulares de cópia de segurança
do sistema de arquivos.
Veja Locais dos arquivos para conhecer
como realocar os arquivos de configuração.
O comando ou função de arquivamento é chamado apenas para segmentos
de WAL inteiramente cheios.
Portanto, se o servidor gerar apenas pouco tráfego de
WAL (ou tiver períodos de ociosidade), poderá
haver um longo atraso entre a conclusão de uma transação e sua
escrita segura no armazenamento de arquivamento.
Para limitar quão antigo são os dados não arquivados, pode-se
definir o parâmetro archive_timeout para
forçar o servidor a alternar para um novo arquivo de segmento de
WAL com pelo menos esta frequência.
Note que os arquivos arquivados antecipadamente devido a uma
alternância forçada, ainda têm o mesmo tamanho que os arquivos
completamente cheios.
Portanto, não é aconselhável definir um
archive_timeout muito baixo —
isto irá inflar o armazenamento do arquivamento.
As configurações de archive_timeout de um minuto
ou mais são geralmente razoáveis.
Além disso, pode-se forçar uma alternância de segmento manualmente
usando a função pg_switch_wal, se for desejado
garantir que uma transação recém-concluída seja arquivada o mais
rápido possível.
Outras funções utilitárias relacionadas ao gerenciamento do
WAL estão listadas na
Tabela 9.97.
Quando wal_level está definido como
minimal, alguns comandos SQL
são otimizados para evitar a escrita no WAL,
conforme descrito em Desativação do arquivamento do WAL e replicação por fluxo.
Se a replicação por arquivamento ou fluxo fosse ativada durante
a execução de uma dessas instruções, o WAL não
teria informações suficientes para a restauração pelo arquivamento.
(A restauração devido a falhas não é afetada.)
Por esta razão, o wal_level só pode ser alterado
na carga do servidor.
Entretanto, archive_command e
archive_library pode ser alterado com uma
recarga do arquivo de configuração.
Se estiver sendo arquivado via interpretador de comandos e se
desejar interromper temporariamente o processo de arquivamento,
uma maneira de fazer isto é definir archive_command
como a cadeia de caracteres vazia ('').
Isto fará com que os arquivos de WAL se acumulem
no diretório pg_wal/ até que seja restabelecido
um archive_command funcional.
A maneira mais fácil de criar uma cópia de segurança base é usando a ferramenta pg_basebackup. Pode ser criada uma cópia de segurança base como arquivos regulares, ou como um arquivo tar. Havendo necessidade de mais flexibilidade do que o pg_basebackup pode fornecer, também se pode fazer uma cópia de segurança base usando a API de baixo nível (veja Criação de cópia de segurança base usando API de baixo nível).
Não é necessário se preocupar com o tempo que leva para criar uma
cópia de segurança base.
Entretanto, se o servidor for normalmente executado com
full_page_writes inativo, poderá ser notada
uma queda no desempenho enquanto a cópia de segurança é criada,
porque full_page_writes é efetivamente forçado
durante o modo de cópia de segurança.
Para fazer uso da cópia de segurança, será necessário preservar todos
os arquivos de segmento de WAL gerados durante e
após a cópia de segurança do sistema de arquivos.
Para ajudar, o processo de cópia de segurança base cria um
arquivo de histórico de cópia de segurança,
que é imediatamente armazenado na área de arquivo do
WAL.
Este arquivo recebe o nome do primeiro arquivo de segmento de
WAL necessário para a cópia de segurança do
sistema de arquivos.
Por exemplo, se o arquivo de WAL inicial for
0000000100001234000055CD, o arquivo de histórico
de cópia de segurança terá um nome como
0000000100001234000055CD.007C9330.backup.
(A segunda parte do nome do arquivo representa a posição exata
dentro do arquivo de WAL, e normalmente pode ser
ignorada.)
Após arquivar com segurança a cópia de segurança do sistema de
arquivos e os arquivos de segmento de WAL
usados durante a cópia de segurança (conforme especificado no
arquivo de histórico da cópia de segurança), todos os segmentos de
WAL arquivados com nomes numericamente inferiores
não serão mais necessários para restaurar a cópia de segurança do
sistema de arquivos, podendo ser excluídos.
Entretanto, deve-se considerar manter vários conjuntos de cópia
de segurança para ter certeza de que é possível restaurar os dados.
O arquivo de histórico de cópia de segurança é apenas um pequeno arquivo de texto. Ele contém a cadeia de caracteres de rótulo fornecida para o pg_basebackup, bem como os horários inicial e final e os segmentos de WAL da cópia de segurança. Se foi usado o rótulo para identificar o arquivo de cópia de segurança associado, o arquivo de histórico arquivado é suficiente para informar qual arquivo de cópia de segurança restaurar.
Como é necessário preservar todos os arquivos de WAL arquivados desde a última cópia de segurança base, o intervalo entre as cópia de segurança base deve ser escolhido com base na quantidade de armazenamento que se deseja usar para arquivos de WAL arquivados. Também deve-se considerar quanto tempo se está disposto a gastar na restauração, se esta for necessária — o sistema terá que reproduzir todos estes segmentos de WAL, e isto pode demorar um pouco, se já passou muito tempo desde a última cópia de segurança base.
Pode-se usar o pg_basebackup para realizar uma
cópia de segurança incremental especificando a opção
--incremental.
Deve ser fornecido como argumento para --incremental
o manifesto de uma cópia de segurança anterior do mesmo servidor.
Na cópia de segurança resultante, os arquivos que não são de relação
serão incluídos na íntegra, mas alguns arquivos de relação poderão
ser substituídos por arquivos incrementais menores, contendo apenas
os blocos alterados desde a cópia de segurança anterior e metadados
suficientes para reconstruir a versão corrente do arquivo.
Para determinar quais blocos precisam de uma cópia de segurança,
o servidor usa resumos de WAL armazenados
no diretório de dados, dentro do diretório
pg_wal/summaries.
Se os arquivos de resumo requeridos não estiverem presentes, a
tentativa de realizar uma cópia de segurança incremental irá falhar.
Os resumos presentes neste diretório devem abranger todos os LSNs,
desde o LSN inicial da cópia de segurança anterior até o LSN
inicial da cópia de segurança corrente.
Como o servidor procura por resumos de WAL logo
após estabelecer o LSN inicial da cópia de segurança corrente,
é provável que os arquivos de resumo necessários não estejam
imediatamente presentes no disco, mas o servidor aguardará o
surgimento de quaisquer arquivos ausentes.
Isto também ajuda caso o processo de sumarização do
WAL tenha ficado atrasado.
Entretanto, se os arquivos necessários já tiverem sido removidos,
ou se o sumarizador de WAL não acompanhar a
velocidade necessária, a cópia de segurança incremental irá falhar.
Ao restaurar uma cópia de segurança incremental, será necessário ter
não apenas a própria cópia de segurança incremental, mas também
todas as cópias de segurança anteriores necessárias para fornecer
os blocos omitidos da cópia de segurança incremental.
Veja pg_combinebackup para obter mais
informações sobre este requisito.
Note-se que existem restrições quanto ao uso do
pg_combinebackup quando o status da
soma de verificação (checksum) da
instância (cluster) tiver sido
alterado; veja “Limitações”.
Note-se que todos os requisitos para usar uma cópia de segurança
completa também se aplicam a uma cópia de segurança incremental.
Por exemplo, ainda se precisa de todos os arquivos de segmento de
WAL gerados durante e após a cópia de segurança
do sistema de arquivos, bem como de quaisquer arquivos de histórico
de WAL relevantes.
E ainda será necessário criar um recovery.signal
(ou standby.signal) e realizar a restauração,
conforme descrito em Restauração usando uma cópia de segurança de arquivamento contínuo.
A necessidade de ter cópias de segurança anteriores disponíveis no
momento da restauração e de utilizar o
pg_combinebackup é um requisito adicional a
todos os outros.
Lembre-se de que o PostgreSQL não possui
um mecanismo integrado para determinar quais cópias de segurança
ainda são necessárias como base para restaurar cópias de segurança
incrementais posteriores.
Deve-se manter o controle das relações entre as cópias de segurança
completas e incrementais por conta própria, e certificar-se de não
remover cópias de segurança anteriores caso sejam necessários para
restaurar cópias de segurança incrementais posteriores.
Cópias de segurança incrementais geralmente só fazem sentido para bancos de dados relativamente grandes, nos quais uma parcela significativa dos dados não sofre alterações ou muda apenas lentamente. Para bancos de dados pequenos, é mais simples ignorar a existência de cópias de segurança incrementais e realizar apenas cópias de segurança completas, que são mais fáceis de gerenciar. Para um banco de dados grande que é extensivamente modificado, as cópia de seguranças incrementais não serão muito menores que as cópias de segurança completas.
Uma cópia de segurança incremental só será possível se a reprodução começar a partir de um ponto de verificação posterior ao da cópia de segurança anterior da qual depende. Se a cópia de segurança incremental for feita no servidor primário, esta condição será sempre satisfeita, porque cada cópia de segurança dispara um novo ponto de verificação. Em servidores em-espera (standby), a reprodução começa a partir do ponto de reinicio mais recente. Portanto, uma cópia de segurança incremental de um servidor em-espera poderá falhar se tiver havido pouquíssima atividade desde a cópia de segurança anterior, uma vez que nenhum novo ponto de reínicio (restartpoint) pode ter sido criado.
Em vez de criar uma cópia de segurança base completa ou incremental usando o pg_basebackup, pode-se criar uma cópia de segurança base usando a API de baixo nível. Este procedimento envolve algumas etapas a mais do que o método para pg_basebackup, mas é relativamente simples. É muito importante que estas etapas sejam executadas em sequência, e que o sucesso de uma etapa seja verificado antes de prosseguir para a próxima.
É possível executar várias cópias de segurança simultaneamente (tanto as iniciadas usando esta API de cópia de segurança, quanto as iniciadas usando pg_basebackup).
Certifique-se de que o arquivamento de WAL esteja ativado e em funcionamento.
Conecte-se ao servidor (não importa em qual banco de dados) como um
usuário com direitos de executar pg_backup_start
(superusuário ou um usuário ao qual foi concedido o privilégio
EXECUTE na função) e execute o comando:
SELECT pg_backup_start(label => 'label', fast => false);
onde label é qualquer cadeia de caracteres que
se queira usar para identificar de forma única esta operação de
cópia de segurança.
A conexão que chama pg_backup_start deve ser
mantida até o final da cópia de segurança; caso contrário a
cópia de segurança será automaticamente interrompida.
Cópias de segurança em-linha são sempre iniciadas no começo de
um ponto de verificação.
Por padrão, pg_backup_start irá aguardar a
conclusão do próximo ponto de verificação programado, o que pode
levar muito tempo (veja os parâmetros de configuração
checkpoint_timeout e
checkpoint_completion_target).
Isto geralmente é preferível, porque minimiza o impacto no sistema
em execução.
Caso se deseje iniciar a cópia de segurança o mais rápido possível,
deve-se passar true como segundo parâmetro para
pg_backup_start e será solicitado um ponto de
verificação imediato, que será concluído o mais rápido possível,
usando o máximo de E/S possível.
Crie a cópia de segurança usando qualquer ferramenta de cópia de segurança de sistema de arquivos conveniente, como tar ou cpio (e não pg_dump ou pg_dumpall). Não é necessário nem desejável interromper a operação normal do servidor de banco de dados enquanto se faz isto. Veja em Cópia de segurança do diretório de dados coisas a se considerar durante esta cópia de segurança.
Na mesma conexão de antes, execute o comando:
SELECT * FROM pg_backup_stop(wait_for_archive => true);
Isto encerra o modo de cópia de segurança.
No servidor primário também é realizada uma alternância automática
para o próximo segmento de WAL.
No servidor em-espera não é possível alternar automaticamente
entre os segmentos de WAL, então pode-se querer
executar pg_switch_wal no servidor primário
para realizar uma alternância manual.
O motivo da alternância é garantir que o último arquivo de segmento
de WAL escrito durante o intervalo de
cópia de segurança esteja pronto para arquivamento.
pg_backup_stop irá retornar uma linha com
três valores.
O segundo desses campos deve ser escrito em um arquivo chamado
backup_label no diretório raiz da
cópia de segurança.
O terceiro campo deve ser escrito em um arquivo chamado
tablespace_map, a menos que o campo esteja vazio.
Estes arquivos são vitais para o funcionamento da cópia de segurança
e devem ser escritos byte a byte, sem modificações, o que pode
exigir a abertura do arquivo em modo binário.
Assim que os arquivos de segmento de WAL ativos
durante a cópia de segurança forem arquivados, o processo estará
concluído.
O arquivo identificado pelo primeiro valor retornado por
pg_backup_stop é o último segmento necessário
para formar um conjunto completo de arquivos de cópia de segurança.
No servidor primário, se archive_mode estiver
ativo e o parâmetro wait_for_archive for
true, então pg_backup_stop
não irá retornar até que o último segmento tenha sido arquivado.
No servidor em-espera, archive_mode deverá ser
always para que
pg_backup_stop aguarde.
O arquivamento desses arquivos ocorre automaticamente, uma vez que
já se realizou a configuração de archive_command
ou archive_library.
Na maioria dos casos, isto ocorre rapidamente, mas recomenda-se
monitorar o sistema de arquivamento para garantir que não haja atrasos.
Se o processo de arquivamento sofrer atrasos devido a falhas no
comando ou na biblioteca de arquivamento, ele continuará tentando
novamente até que o arquivamento seja bem-sucedido e a
cópia de segurança esteja concluído.
Caso se deseje definir um limite de tempo para a execução de
pg_backup_stop, deve-se definir um valor
apropriado para statement_timeout,
mas note-se que, se pg_backup_stop terminar
devido a isto, a cópia de segurança poderá não ser válida.
Se o processo de cópia de segurança monitorar e garantir que todos
os arquivos de segmento de WAL necessários para
a cópia de segurança sejam arquivados com sucesso, então o
parâmetro wait_for_archive (cujo padrão é verdade)
poderá ser definido como falso para fazer com que
pg_backup_stop retorne assim que o registro
de parada da cópia de segurança seja escrito no WAL.
Por padrão, pg_backup_stop irá aguardar até
que todo o WAL tenha sido arquivado, o que pode
levar algum tempo.
Esta opção deve ser usada com cuidado: se o arquivamento de
WAL não for monitorado corretamente, a
cópia de segurança poderá não incluir todos os arquivos de
WAL e, portanto, ficará incompleta e não poderá
ser restaurada.
Algumas ferramentas de cópia de segurança do sistema de arquivos
emitem avisos ou erros se os arquivos que estão tentando
copiar forem alterados durante a cópia.
Ao realizar uma cópia de segurança base de um banco de dados ativo,
esta situação é normal e não um erro.
Entretanto, é necessário garantir que se possa distinguir
advertências desse tipo, de erros reais.
Por exemplo, algumas versões do rsync
retornam um código de saída separado para
“arquivos fonte desaparecidos”, e se pode escrever
um script que aceite este código de saída como não sendo um erro.
Além disso, algumas versões do tar do
GNU retornam um código de erro indistinguível
de um erro fatal, se o arquivo for truncado enquanto o
tar o estava copiando.
Felizmente, o tar do GNU,
versão 1.16 e posteriores, retornam 1 se o arquivo foi alterado
durante a cópia de segurança, e 2 para os outros erros.
Com o tar do GNU,
versão 1.23 e posteriores, pode-se usar as opções de aviso
--warning=no-file-changed --warning=no-file-removed
para ocultar as mensagens de aviso relacionadas.
Certifique-se de que a cópia de segurança inclua todos os arquivos
do diretório de dados (por exemplo,
/usr/local/pgsql/data).
Se estiver sendo usado espaços de tabelas que não residem abaixo
desse diretório, deve-se ter o cuidado de incluí-los também
(e certificar-se de que a cópia de segurança arquive as
ligações simbólicas como ligações, caso contrário a
restauração irá corromper os espaços de tabelas).
Entretanto, deve-se omitir da cópia de segurança os arquivos dentro
do diretório pg_wal da instância.
Este pequeno ajuste vale a pena, porque reduz o risco de erros na
restauração.
Isto será fácil de obter se pg_wal for uma
ligação simbólica apontando para algum lugar fora do diretório de
dados da instância, que é uma configuração comum de qualquer maneira
por motivos de desempenho.
Também pode-se querer omitir os arquivos
postmaster.pid e
postmaster.opts, que registram informações
sobre o postmaster em execução, e não
sobre o postmaster que usará no futuro
a cópia de segurança.
(Estes arquivos podem confundir o pg_ctl.)
Muitas vezes, é uma boa ideia também omitir da cópia de segurança
os arquivos dentro do diretório pg_replslot/
da instância, para que os encaixes de replicação existentes no
servidor primário não se tornem parte da cópia de segurança.
Caso contrário, o uso subsequente da cópia de segurança para criar
um servidor em-espera poderá resultar na retenção indefinida de
arquivos de WAL no servidor em-espera e,
possivelmente, sobrecarregar o servidor primário, se as mensagens de
retorno do servidor em-espera Hot Standby
estiverem ativas, porque os clientes que estão usando estes encaixes
de replicação ainda estarão se conectando e atualizando os encaixes
no servidor primário, e não no servidor em-espera.
Mesmo que a cópia de segurança seja apenas para uso na criação de
um novo servidor primário, não se espera que copiar os encaixes de
replicação seja particularmente útil, porque o conteúdo desses
encaixes provavelmente estará muito desatualizado quando o novo
servidor primário entrar em operação.
O conteúdo dos diretórios pg_dynshmem/,
pg_notify/, pg_serial/,
pg_snapshots/, pg_stat_tmp/,
e pg_subtrans/ (mas não os próprios diretórios)
podem ser omitidos da cópia de segurança, porque serão inicializados
na ativação do postmaster.
Qualquer arquivo ou diretório que comece por
pgsql_tmp pode ser omitido da cópia de segurança.
Estes arquivos são removidos na carga do
postmaster, e os diretórios serão
recriados conforme necessário.
Os arquivos pg_internal.init poderão ser
omitidos da cópia de segurança, sempre que um arquivo com este nome
for encontrado.
Estes arquivos contêm dados de cache
de relação que sempre são reconstruídos durante a restauração.
O arquivo de rótulo de cópia de segurança inclui a cadeia de
caracteres de rótulo fornecida para a função
pg_backup_start, bem como a hora em que a
função pg_backup_start foi executada e o nome
do arquivo de WAL inicial.
Em caso de confusão, é possível olhar o arquivo de rótulo de
cópia de segurança e determinar exatamente de qual sessão de
cópia de segurança o arquivo de cópia de segurança veio.
O arquivo de mapa de espaços de tabelas inclui os nomes das
ligações simbólicas conforme existem no diretório
pg_tblspc/, e o caminho completo de cada
ligação simbólica.
Estes arquivos não são meramente informativos; suas presenças e
conteúdo são essenciais para a operação adequada do processo de
restauração do sistema.
Também é possível fazer a cópia de segurança com o servidor parado.
Neste caso, obviamente não se pode usar as funções
pg_backup_start e
pg_backup_stop e, portanto, será deixado por
sua conta identificar qual cópia de segurança é qual, e até que
ponto os arquivos de WAL associado devem ir.
Geralmente é melhor seguir o procedimento de arquivamento contínuo
mostrado acima.
Certo, o pior já aconteceu, sendo necessário executar a restauração a partir da cópia de segurança. A seguir está o procedimento:
Pare o servidor, se estiver em execução.
Se houver espaço para fazer isto, copie todo o diretório de dados
da instância e de quaisquer espaços de tabelas para um local
temporário, caso precise deles posteriormente.
Note que esta precaução exigirá que haja espaço livre suficiente
no sistema para manter duas cópias do banco de dados existente.
Se não houver espaço suficiente, deve-se salvar pelo menos o
conteúdo do subdiretório pg_wal da instância,
porque ele poderá conter arquivos de WAL que
não foram arquivados antes do sistema cair.
Remova todos os arquivos e subdiretórios existentes no diretório de dados da instância, e nos diretórios raiz de quaisquer espaços de tabelas que se estiver sendo usado.
Se estiver sendo restaurada uma cópia de segurança completa,
poderão ser restaurados os arquivos do banco de dados diretamente
nos diretórios de destino.
Certifique-se de que sejam restaurados com o dono correto
(o usuário do sistema de banco de dados, e não o usuário
root!) e com as permissões corretas.
Se estiver sendo usado espaços de tabela, deve-se verificar se as
ligações simbólicas em pg_tblspc/ foram
restaurados corretamente.
Se estiver sendo restaurada uma cópia de segurança incremental, será necessário restaurar a cópia de segurança incremental e todas as cópias de segurança anteriores das quais ela depende direta ou indiretamente na máquina onde está sendo realizada a restauração. Estas cópias de segurança precisarão ser colocadas em diretórios separados, e não nos diretórios de destino onde se deseja que o servidor em execução fique. Assim que isto for feito, deve-se usar o pg_combinebackup para extrair os dados da cópia de segurança completa e de todas as cópias de segurança incrementais subsequentes, e para escrever uma cópia de segurança completa sintético nos diretórios de destino. Como mencionado acima, deve-se verificar se as permissões e as ligações simbólicas dos espaços de tabelas estão corretos.
Remova todos os arquivos presentes no diretório
pg_wal;
eles vieram da cópia de segurança do sistema de arquivos e,
portanto, provavelmente são obsoletos em vez de atuais.
Se o diretório pg_wal não foi arquivado,
recrie-o com as permissões apropriadas, tendo o cuidado de
restabelecê-lo como um vínculo simbólico, caso tenha sido
configurado dessa forma antes.
Se os arquivos de segmento de WAL salvos na
etapa 2 foram desarquivados, copie-os para o diretório
pg_wal.
(É melhor copiá-los, e não movê-los, para que ainda se tenha os
arquivos não modificados se ocorrer um problema e for necessário
começar de novo.)
Defina as configurações de restauração no arquivo
postgresql.conf
(veja Restauração do arquivamento)
e crie o arquivo recovery.signal no diretório
de dados da instância.
Também pode-se modificar temporariamente o arquivo
pg_hba.conf, para impedir que usuários comuns
se conectem até que se tenha certeza de que a restauração foi
bem-sucedida.
Ative o servidor.
O servidor entrará no modo de restauração e procederá à leitura
dos arquivos de WAL arquivados necessários.
Caso a restauração seja encerrada devido a um erro externo, o
servidor pode simplesmente ser reiniciado e continuará a restauração.
Após a conclusão do processo de restauração, o servidor removerá
o arquivo recovery.signal (para evitar a
reentrada acidental no modo de restauração mais tarde)
e, em seguida, iniciar as operações normais do banco de dados.
Inspecione o conteúdo do servidor para garantir que foi
restaurado o estado desejado.
Se não, volte ao passo 1.
Se tudo estiver bem, permita que os usuários se conectem
voltando pg_hba.conf ao normal.
A parte chave de tudo isto é definir uma configuração de restauração
que descreva como se deseja restaurar, e até que ponto a restauração
deve ser executada.
A única coisa que com certeza se deve especificar é o
restore_command, que informa ao
PostgreSQL como restaurar segmentos
de arquivo de WAL arquivados.
Como o archive_command, esta é uma cadeia de
caracteres de comando para o interpretador de comandos.
Pode conter %f, que é substituído pelo nome do
arquivo de WAL desejado, e %p,
que é substituído pelo nome do caminho para o qual copiar o arquivo
de WAL.
(O nome do caminho é relativo ao diretório de trabalho corrente,
ou seja, o diretório de dados da instância.)
Deve-se usar %% se for necessário incorporar um
caractere % real no comando.
O comando útil mais simples é algo como:
restore_command = 'cp /mnt/server/archivedir/%f %p'
que irá copiar os segmentos de WAL previamente
arquivados do diretório /mnt/server/archivedir.
É claro que se pode usar algo muito mais complicado, talvez até
mesmo um script do interpretador de comandos que solicite ao
operador a montagem de uma fita apropriada.
É importante que o comando retorne um status de saída diferente de zero em caso de falha. O comando será chamado solicitando arquivos que não estão presentes no arquivamento; deverá retornar um valor diferente de zero quando isto acontecer. Esta não é uma condição de erro. A exceção é que se o comando for encerrado por um sinal (diferente de SIGTERM, usado como parte da parada do servidor), ou um erro do interpretador de comandos (como comando não encontrado), a restauração será interrompida, e o servidor não irá iniciar.
Nem todos os arquivos requeridos serão arquivos de segmento de
WAL; também deve-se esperar requisições de
arquivos com o sufixo .history.
Também deve-se estar ciente de que o nome base do caminho
%p será diferente de %f;
não espere que sejam intercambiáveis.
Os segmentos de WAL que não puderem ser
encontrados no arquivamento serão procurados no diretório
pg_wal;
isto permite o uso de segmentos recentes não arquivados.
Entretanto, os segmentos disponíveis no arquivamento serão usados
preferencialmente aos arquivos em pg_wal.
Normalmente, a restauração prosseguirá por todos os segmentos de
WAL disponíveis, restaurando assim o banco de
dados para o ponto corrente no tempo (ou o mais próximo possível,
dado os segmentos de WAL disponíveis).
Portanto, uma restauração normal terminará com a mensagem
“arquivo não encontrado”, com o texto exato da mensagem
de erro dependendo da escolha do restore_command.
Também pode ser vista uma mensagem de erro no início da restauração
para um arquivo chamado algo como 00000001.history.
Isto também é normal, não indicando problema em situações simples
de restauração; veja detalhes em Linhas do tempo.
Se for desejado restaurar para algum ponto anterior no tempo (digamos, logo antes do DBA júnior descartar a tabela de transações principal), deve-se apenas especificar o ponto de parada. Pode-se especificar o ponto de parada, conhecido como “meta da restauração”, por data/hora, ponto de restauração indicado, ou pela conclusão de um identificador de transação específico. No momento em que este texto foi escrito, apenas as opções de data/hora e ponto de restauração indicado são realmente úteis, porque não há ferramentas para ajudar a identificar com precisão qual identificador de transação a ser usado.
O ponto de parada deve ser especificado após a hora do fim da
cópia de segurança base, ou seja, após a hora do término da
função pg_backup_stop.
Não se pode usar uma cópia de segurança base para restaurar para
um momento em que a cópia de segurança estava em andamento.
(Para restaurar até este momento, deve-se voltar à cópia de
segurança base anterior e avançar a partir daí.)
Se a restauração encontrar dados de WAL
corrompidos, a restauração será interrompida neste ponto, e o
servidor não será iniciado.
Neste caso, o processo de restauração poderá ser executado novamente
desde o início, especificando uma “meta de restauração”
anterior ao ponto corrompido, para que a restauração possa ser
concluída normalmente.
Se a restauração falhar por um motivo externo, como uma falha no
sistema, ou se o arquivo de WAL ficar inacessível,
a restauração poderá simplesmente ser reiniciada, e será reiniciada
quase de onde parou.
O reinício da restauração funciona de forma semelhante ao ponto de
verificação em operação normal: o servidor força periodicamente
a escrita de todo o seu estado para o disco e, em seguida, atualiza
o arquivo pg_control para indicar que os dados
de WAL já processados não precisam ser verificados
novamente.
A capacidade de restaurar o banco de dados para um ponto anterior no tempo cria algumas complexidades semelhantes às histórias de ficção científica sobre viagens no tempo e universos paralelos. Por exemplo, na história original do banco de dados, vamos supor que se tenha removido uma tabela crítica às 17h15 na tarde de terça-feira, mas não se tenha percebido isto até o meio-dia de quarta-feira. Imperturbável, se pega a cópia de segurança, restaura para o ponto no tempo às 17h14 da tarde de terça-feira, e está tudo em ordem novamente. Nesta história do universo do banco de dados, nunca se removeu a tabela. Mas supondo que mais tarde se perceba que esta não foi uma boa ideia, e seria bom voltar para a manhã de quarta-feira da história original. Isto não seria possível se, enquanto o banco de dados estava funcionando, ele tivesse sobrescrito alguns dos arquivos de segmento de WAL que levavam até o momento que agora se deseja poder voltar. Assim, para evitar esta situação, é necessário distinguir a série de arquivos de WAL gerados após a restauração pontual, daqueles arquivos que foram gerados na história original do banco de dados.
Para lidar com este problema, o PostgreSQL
tem a noção de linhas do tempo
(timelines).
Sempre que uma restauração de arquivamento é concluída, é criada
uma nova linha do tempo para identificar a série de arquivos de
WAL gerados após esta restauração.
O número de identificação da linha do tempo faz parte dos nomes dos
arquivos de segmento de WAL, portanto, uma nova
linha do tempo não substitui os dados de WAL
gerados por linhas do tempo anteriores.
Por exemplo, no nome do arquivo de WAL
0000000100001234000055CD, o
00000001 inicial é o ID da linha do tempo em
hexadecimal.
(Note-se que, em outros contextos, como mensagens de registro do
servidor, os IDs de linha do tempo geralmente são mostrados em decimal.)
Na verdade, é possível arquivar muitas linhas do tempo diferentes. Embora possa parecer um recurso inútil, muitas vezes é um salva-vidas. Considere a situação em que não se tem certeza sobre qual é o ponto no tempo, até o qual se deva restaurar e, portanto, é necessário fazer várias restaurações pontuais por tentativa e erro até encontrar o melhor local para ramificar da história antiga. Sem as linhas do tempo, este processo logo geraria uma confusão incontrolável. Com as linhas do tempo, pode-se restaurar para qualquer estado anterior, incluindo estados em ramificações de linha do tempo abandonadas anteriormente.
Toda vez que uma nova linha do tempo é criada, o PostgreSQL cria um arquivo de “histórico de linha do tempo”, que mostra de qual linha do tempo ela se ramificou, e quando. Estes arquivos de histórico são necessários para permitir que o sistema escolha os arquivos de segmento de WAL corretos ao restaurar de um arquivamento contendo várias linhas do tempo. Portanto, eles são arquivados na área de arquivamento do WAL, exatamente como os arquivos de segmento do WAL. Os arquivos de histórico são apenas pequenos arquivos de texto; por isto, é barato e apropriado mantê-los indefinidamente (ao contrário dos arquivos de segmento, que são grandes). É possível, se for desejado, adicionar comentários a um arquivo de histórico para registrar anotações próprias sobre como e por que esta linha do tempo específica foi criada. Estes comentários serão especialmente valiosos quando se tiver um emaranhado de diferentes linhas do tempo como resultado da experimentação.
O comportamento padrão da restauração é restaurar para a linha do
tempo mais recente encontrada no arquivamento.
Se for desejado restaurar para a linha do tempo corrente quando a
cópia de segurança base foi feita, ou para uma linha do tempo
filha específica (ou seja, se deseja retornar a algum estado
gerado após uma tentativa de restauração), é necessário
especificar current, ou o identificador da
linha do tempo desejada, no parâmetro
recovery_target_timeline.
Não se pode restaurar usando linhas do tempo que se ramificaram
antes da cópia de segurança base ter sido criada.
Aqui são fornecidas algumas dicas para configurar o arquivamento contínuo.
É possível usar os recursos de cópia de segurança do PostgreSQL para produzir Hot-Backups autônomos. Estas são cópias de segurança que não podem ser usadas para restauração pontual, mas normalmente são muito mais rápidas para cópia de segurança e restauração do que as cópias de segurança feitas pelo utilitário pg_dump. (Elas também são muito maiores que as cópias de segurança feitas pelo pg_dump, portanto, em alguns casos, a vantagem da velocidade pode ser negada.)
Assim como nas cópias de segurança base, a maneira mais fácil de
produzir um Hot-Backup autônomo
é usando o utilitário pg_basebackup
(veja também Servidor em-espera ativo (Hot Standby)).
Se for incluído o parâmetro -X ao chamá-lo,
todo o WAL necessário para usar a cópia de
segurança será incluído na cópia de segurança automaticamente,
e nenhuma ação especial será necessária para restaurar a
cópia de segurança.
Se o tamanho de armazenamento do arquivamento for uma preocupação, pode-se usar o utilitário gzip para comprimir os arquivos arquivados:
archive_command = 'gzip < %p > /mnt/server/archivedir/%f.gz'
Então será necessário usar o utilitário gunzip durante a restauração:
restore_command = 'gunzip < /mnt/server/archivedir/%f.gz > %p'
Muitas pessoas optam por usar scripts na definição do
archive_command, para que a entrada no arquivo
postgresql.conf pareça bem simples:
archive_command = 'local_backup_script.sh "%p" "%f"'
Usar um arquivo de script separado é aconselhável sempre que se quiser usar mais de um único comando no processo de arquivamento. Isto permite que toda a complexidade seja gerenciada dentro do script, que pode ser escrito em uma linguagem de script popular, como bash ou perl.
Exemplos de requisitos que podem ser resolvidos por um script incluem:
Copiar os dados para um armazenamento de dados externo seguro
Agrupar arquivos de WAL para serem transferidos a cada três horas, em vez de um de cada vez
Interface com outro software de cópia de segurança e restauração
Interface com software de monitoramento para relatar erros
Ao usar um script no archive_command,
é desejável ativar o logging_collector.
Quaisquer mensagens escritas em stderr
a partir do script aparecerão no log
do servidor de banco de dados, permitindo que configurações
complexas sejam diagnosticadas facilmente se falharem.
No momento em que este texto foi escrito, existiam várias limitações para a técnica de arquivamento contínuo. Estas provavelmente serão corrigidas em versões futuras:
Se for executado o comando CREATE DATABASE
enquanto uma cópia de segurança base estiver sendo feita,
e então o banco de dados modelo que o comando
CREATE DATABASE copiou é modificado enquanto a
cópia de segurança base continua em andamento,
é possível que a restauração faça com que estas modificações
também sejam propagadas no banco de dados criado.
Claro que isto é indesejável.
Para evitar este risco, é melhor não modificar nenhum banco de
dados modelo ao fazer uma cópia de segurança base.
Os comandos CREATE TABLESPACE são registrados no WAL com o caminho absoluto literal e, portanto, serão reproduzidos como criações de espaços de tabelas com o mesmo caminho absoluto. Isto poderá ser indesejável se o WAL estiver sendo reproduzido em uma máquina diferente. Pode ser perigoso, mesmo se o WAL estiver sendo reproduzido na mesma máquina, mas em um novo diretório de dados: a reprodução sobrescreverá o conteúdo do espaço de tabelas original. Para evitar possíveis problemas desse tipo, a melhor prática é fazer uma nova cópia de segurança base após criar ou remover espaços de tabelas.
Também deve-se notar que o formato padrão do WAL
é bastante volumoso, porque inclui muitos instantâneos de página de
disco.
Estes instantâneos de página são projetados para oferecer suporte
à recuperação de falhas, porque talvez seja necessário corrigir
páginas de disco parcialmente escritas.
Dependendo do hardware e do software do sistema, o risco de escritas
parciais pode ser pequeno o suficiente para ser ignorado, caso em que
se pode reduzir muito o volume total de WAL
arquivado, desativando os instantâneos de página usando
o parâmetro full_page_writes.
(Leia as notas e advertências em Confiabilidade e o Registro de Escrita Antecipada antes de
fazer isto.)
A desativação dos instantâneos de página não impede o uso de
WAL para operações de PITR.
Uma área para desenvolvimento futuro é comprimir os dados de
WAL arquivados removendo as cópias de páginas
desnecessárias, mesmo quando full_page_writes
estiver ativo.
Neste ínterim, os administradores podem desejar reduzir o número
de instantâneos de página incluídos no WAL
aumentando os parâmetros de intervalo do ponto de verificação
tanto quanto possível.
[145] Um método de registro de transação no qual o registro é sempre escrito antes dos dados. Glosbe – write-ahead log (N. T.)