25.3. Arquivamento contínuo e restauração para um ponto-no-tempo (PITR) #

25.3.1. Configuração de arquivamento do WAL
25.3.2. Criação de cópia de segurança base
25.3.3. Criação de cópia de segurança incremental
25.3.4. Criação de cópia de segurança base usando API de baixo nível
25.3.5. Restauração usando uma cópia de segurança de arquivamento contínuo
25.3.6. Linhas do tempo
25.3.7. Dicas e exemplos
25.3.8. Ressalvas

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:

Nota

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.

25.3.1. Configuração de arquivamento do 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.

25.3.2. Criação de cópia de segurança base #

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.

25.3.3. Criação de cópia de segurança incremental #

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.

25.3.4. Criação de cópia de segurança base usando API de baixo nível #

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).

  1. Certifique-se de que o arquivamento de WAL esteja ativado e em funcionamento.

  2. 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.

  3. 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.

  4. 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.

  5. 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.

25.3.4.1. Cópia de segurança do diretório de dados #

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.

25.3.5. Restauração usando uma cópia de segurança de arquivamento contínuo #

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:

  1. Pare o servidor, se estiver em execução.

  2. 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.

  3. 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.

  4. 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.

  5. 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.

  6. 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.

  7. 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.)

  8. 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.

  9. 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.

  10. 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.

Nota

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.

25.3.6. Linhas do tempo #

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.

25.3.7. Dicas e exemplos #

Aqui são fornecidas algumas dicas para configurar o arquivamento contínuo.

25.3.7.1. Hot-Backups autônomos #

É 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.

25.3.7.2. Registros de arquivamento comprimidos #

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'

25.3.7.3. Scripts de archive_command #

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

Dica

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.

25.3.8. Ressalvas #

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.)