26.2. Servidores em-espera de envio de WAL #

26.2.1. Planejamento
26.2.2. Operação de servidor em-espera
26.2.3. Preparação do servidor primário para servidores em-espera
26.2.4. Configuração de servidor em-espera
26.2.5. Replicação por fluxo
26.2.6. Encaixes de replicação
26.2.7. Replicação em cascata
26.2.8. Replicação síncrona
26.2.9. Arquivamento contínuo em servidores em-espera

Pode ser usado o arquivamento contínuo para criar uma configuração de instância de alta disponibilidade (HA), com um ou mais servidores em-espera prontos para assumir as operações, se o servidor primário falhar. Esta capacidade é amplamente referida como warm standby (passivo, em-espera), ou log shipping (envio de WAL).

O servidor primário e o servidor em-espera trabalham juntos para fornecer esta capacidade, embora os servidores estejam apenas fracamente acoplados. O servidor primário opera em modo de arquivamento contínuo, enquanto cada servidor em-espera opera no modo de restauração contínua, lendo os arquivos de WAL do servidor primário. Não é necessária nenhuma alteração nas tabelas do banco de dados para ativar este recurso, portanto oferece baixo custo administrativo em comparação com algumas outras soluções de replicação. Esta configuração também tem um impacto de desempenho relativamente baixo no servidor primário.

A movimentação direta de registros de WAL de um servidor de banco de dados para outro é normalmente descrita como log shipping. O PostgreSQL implementa o log shipping baseado em arquivo, transferindo um arquivo (segmento de WAL) de cada vez. Os arquivos de WAL (16 MB) podem ser enviados de forma fácil e econômica a qualquer distância, seja para um sistema adjacente, outro sistema no mesmo local, ou outro sistema do outro lado do planeta. A largura de banda necessária para esta técnica varia conforme a taxa de transação do servidor primário. O envio de WAL baseado em registros é mais granular e transmite as alterações do WAL de forma incremental por meio de uma conexão de rede. (veja Replicação por fluxo).

Deve-se notar que o log shipping é assíncrono, ou seja, os registros de WAL são enviados após a efetivação da transação. Como resultado, há uma janela para perda de dados caso o servidor primário sofra uma falha grave; as transações ainda não enviadas serão perdidas. O tamanho da janela de perda de dados no log shipping baseado em arquivo pode ser limitado pelo uso do parâmetro archive_timeout, que pode ser definido tão baixo como alguns segundos. Entretanto, uma configuração muito baixa aumentará substancialmente a largura de banda necessária para o envio de arquivos. A replicação por fluxo (veja Replicação por fluxo) permite uma janela muito menor de perda de dados.

O desempenho da restauração é suficientemente bom para que o servidor em-espera esteja normalmente apenas a alguns instantes de distância da disponibilidade total após ser ativado. Como resultado, isto é chamado de configuração Warm Standby (passivo, em-espera), que oferece alta disponibilidade. A restauração do servidor a partir da cópia de segurança base e aplicação de todos os arquivos de WAL arquivados (rollforward) leva muito mais tempo, de modo que esta técnica oferece apenas uma solução para recuperação de desastres, e não para alta disponibilidade. O servidor em-espera também pode ser usado para instruções de leitura-apenas, caso em que é chamado de servidor Hot-Standby (ativo, em-espera). Veja Servidor em-espera ativo (Hot Standby) para obter mais informações.

26.2.1. Planejamento #

Geralmente, é aconselhável criar os servidores primário e secundário para serem o mais semelhantes possível, pelo menos da perspectiva do servidor de banco de dados. Em particular, os nomes de caminho associados aos espaços de tabelas serão passados sem modificação, portanto os servidores primário e secundário devem ter os mesmos caminhos de montagem para espaços de tabelas, se este recurso for usado. Deve-se ter em mente que, se for ser executado CREATE TABLESPACE no servidor primário, qualquer novo ponto de montagem necessário para o espaço de tabelas deverá ser criado no servidor primário e em todos os servidores em-espera, antes do comando ser executado. O hardware não precisa ser exatamente o mesmo, mas a experiência mostra que manter dois sistemas idênticos é mais fácil do que manter dois sistemas diferentes ao longo da vida útil da aplicação e do sistema. Em qualquer caso, a arquitetura de hardware deve ser a mesma — o envio de, digamos, um sistema de 32 bits para um sistema de 64 bits não funcionará.

De modo geral, não é possível usar log shipping entre servidores com versão principal do PostgreSQL diferentes. É uma política do PostgreSQL Global Development Group não fazer alterações nos formatos de disco durante atualização de versão secundária, portanto é provável que a execução de diferentes níveis de versão secundária entre servidor primário e servidores secundários funcione com êxito. Entretanto, não é oferecido nenhum suporte formal para isto, então se aconselha manter os servidores primário e secundários no mesmo nível de versão, tanto quanto possível. Ao atualizar para uma nova versão secundária, a política mais segura é atualizar primeiro os servidores secundários — é mais provável que uma nova versão secundária seja capaz de ler arquivos de WAL de uma versão secundária anterior, do que o contrário.

26.2.2. Operação de servidor em-espera #

O servidor irá entrar no modo em-espera se existir o arquivo standby.signal no diretório de dados quando o servidor for iniciado.

No modo em-espera, o servidor aplica continuamente o WAL recebido do servidor primário. O servidor em-espera pode ler o WAL de um arquivamento de WAL (veja restore_command), ou diretamente do servidor primário em uma conexão TCP (replicação por fluxo). O servidor em-espera também tentará restaurar qualquer WAL localizado no diretório pg_wal da instância em-espera. Isto normalmente acontece após o reinício do servidor, quando o servidor em-espera reproduz novamente o WAL que foi transmitido do servidor primário antes do reinício, mas também é possível copiar manualmente os arquivos para o diretório pg_wal a qualquer momento para reproduzi-los.

Na ativação, o servidor em-espera começa restaurando todos os arquivos de WAL disponíveis no local de arquivamento, chamando o restore_command. Uma vez que chega ao fim dos arquivos de WAL disponível no local de arquivamento, e o restore_command falha, o servidor em-espera tenta restaurar qualquer arquivo de WAL disponível no diretório pg_wal. Se isto falhar, e tiver sido configurada a replicação por fluxo, o servidor em-espera tentará se conectar ao servidor primário e iniciar o fluxo do WAL a partir do último registro válido encontrado no arquivamento ou em pg_wal. Se isto falhar, ou a replicação por fluxo não estiver configurada, ou se a conexão for desconectada posteriormente, o servidor em-espera voltará para a etapa 1, e tentará restaurar o arquivo a partir do arquivamento novamente. Este ciclo de novas tentativas via arquivamento, pg_wal, e replicação por fluxo, continua até que o servidor seja parado ou promovido

O modo em-espera é encerrado e o servidor passa para a operação normal quando é executado o comando pg_ctl promote, ou é chamada a função pg_promote(). Antes da comutação (failover), qualquer WAL imediatamente disponível no arquivamento ou em pg_wal será restaurado, mas não será feita nenhuma tentativa de conexão com o servidor primário.

26.2.3. Preparação do servidor primário para servidores em-espera #

Configurar o arquivamento contínuo no servidor primário para haver um diretório de arquivamento acessível a partir do servidor em-espera, conforme descrito em Arquivamento contínuo e restauração para um ponto-no-tempo (PITR). O local do arquivamento deverá estar acessível a partir do servidor em-espera, mesmo quando o servidor primário estiver inativo, ou seja, deverá residir no próprio servidor em-espera, ou em outro servidor confiável, e não no servidor primário.

Se for desejado usar a replicação por fluxo, deverá ser configurada a autenticação no servidor primário permitindo conexões de replicação do(s) servidor(es) em-espera; ou seja, criada uma função de banco de dados (role), e fornecida uma entrada ou entradas adequadas no arquivo pg_hba.conf, com o campo do banco de dados definido como replication. Também deve-se garantir que max_wal_senders esteja definido com um valor suficientemente alto no arquivo de configuração do servidor primário. Se forem usados encaixes (slots) de replicação, deve-se assegurar que max_replication_slots esteja configurado suficientemente alto também.

Fazer uma cópia de segurança base conforme descrito em Criação de cópia de segurança base para inicializar o servidor em-espera.

26.2.4. Configuração de servidor em-espera #

Para configurar o servidor em espera, deve ser restaurada a cópia de segurança base obtida do servidor primário (veja Restauração usando uma cópia de segurança de arquivamento contínuo). Criado o arquivo standby.signal no diretório de dados da instância em-espera. Configurado restore_command como um comando simples para copiar arquivos do arquivamento de WAL. Se for planejado ter vários servidores em-espera para fins de alta disponibilidade, deve-se certificar de que recovery_target_timeline esteja definido como latest (o padrão), para indicar que o servidor em-espera deve levar em conta a linha do tempo definida ao comutar (failover) para outro servidor em-espera.

Nota

O restore_command deverá retornar imediatamente se o arquivo não existir; o servidor repetirá o comando novamente, se necessário.

Se for desejado usar a replicação por fluxo, então primary_conninfo deverá ser preenchida com uma cadeia de caracteres de conexão libpq, incluindo o nome do hospedeiro (ou endereço IP), e quaisquer detalhes adicionais necessários para se conectar ao servidor primário. Se o servidor primário precisar de senha para autenticação, a senha também precisará ser especificada em primary_conninfo.

Se estiver sendo configurado o servidor em-espera para fins de alta disponibilidade, deve ser configurado o arquivamento de WAL, as conexões, e a autenticação, como as do servidor primário, porque o servidor em-espera funcionará como servidor primário após a comutação (failover).

Se estiver sendo usado o arquivamento de WAL, seu tamanho poderá ser minimizado usando o parâmetro archive_cleanup_command para remover arquivos que não são mais necessários para o servidor em-espera. O utilitário pg_archivecleanup é projetado especificamente para ser usado com archive_cleanup_command em configurações típicas de um único servidor em-espera, veja pg_archivecleanup. Note, no entanto, que se o arquivamento estiver sendo usado para fins de cópia de segurança, precisarão ser retidos os arquivos necessários para restaurar pelo menos a partir da cópia de segurança base mais recente, mesmo que não sejam mais necessários para o servidor em-espera.

Um exemplo simples de configuração é:

primary_conninfo = 'host=192.168.1.50 port=5432 user=foo ↵
                    password=foopass ↵
                    options=''-c wal_sender_timeout=5000'''
restore_command = 'cp /path/to/archive/%f %p'
archive_cleanup_command = 'pg_archivecleanup /path/to/archive %r'

Pode-se ter qualquer número de servidores em-espera, mas se for usada replicação por fluxo, deve-se certificar que max_wal_senders esteja definido alto o suficiente no servidor primário para permitir que todos os servidores em-espera possam se conectar simultaneamente.

26.2.5. Replicação por fluxo #

Figura 26.5. Replicação por fluxo


A replicação por fluxo (streaming) permite que o servidor em-espera fique mais atualizado do que seria possível com o log shipping baseado em arquivo. O servidor em-espera se conecta ao servidor primário, que transmite os registros de WAL para o servidor em-espera conforme são gerados, sem esperar que o arquivo de WAL fique completo.

A replicação por fluxo é assíncrona por padrão (veja Replicação síncrona), caso em que há um pequeno atraso entre a efetivação da transação no servidor primário e as alterações se tornarem visíveis no servidor em-espera. Entretanto, este atraso é muito menor do que acontece com o log shipping baseado em arquivo, sendo geralmente menos de um segundo, supondo-se que o servidor em-espera seja poderoso o suficiente para acompanhar a carga. Com a replicação por fluxo, não é necessário configurar archive_timeout para reduzir a janela de perda de dados.

Se estiver sendo usada a replicação por fluxo sem arquivamento contínuo, o servidor primário poderá reciclar segmentos de WAL antigos antes que o servidor em-espera os receba. Se isto ocorrer, o servidor em-espera precisará ser reinicializado a partir de uma nova cópia de segurança base. Isto pode ser evitado definindo wal_keep_size com um valor grande o suficiente para garantir que os segmentos de WAL não sejam reciclados muito cedo, ou configurando um encaixe de replicação para o servidor em-espera. Se for configurado um arquivamento de WAL acessível a partir do servidor em-espera, estas soluções não serão necessárias, porque o servidor em-espera sempre poderá usar o arquivamento para se recuperar, desde que sejam retidos segmentos suficientes.

Para usar a replicação por fluxo, deve ser configurado um servidor em-espera no modo de envio de registros de transação baseado em arquivo, conforme descrito em Servidores em-espera de envio de WAL. A etapa que transforma o servidor em-espera no modo de log-shipping baseado em arquivo em um servidor em-espera no modo de replicação por fluxo, é definindo a configuração de primary_conninfo para apontar para o servidor primário. Deve-se definir listen_addresses e as opções de autenticação (veja pg_hba.conf) no servidor primário, para que o servidor em-espera possa se conectar ao pseudo-banco de dados replication no servidor primário (veja Autenticação).

Em sistemas que oferecem suporte à opção de soquete keepalive, configurar tcp_keepalives_idle, tcp_keepalives_interval e tcp_keepalives_count ajuda o servidor primário perceber prontamente uma conexão interrompida.

Deve-se definir o número máximo de conexões simultâneas dos servidores em-espera (veja max_wal_senders para obter detalhes).

Quando o servidor em-espera é ativado, e primary_conninfo está definido corretamente, o servidor em-espera irá se conectar ao servidor primário após reproduzir todos os arquivos de WAL disponíveis no arquivamento. Se a conexão for estabelecida com sucesso, será visto um processo walreceiver no servidor em-espera, e um processo walsender correspondente no servidor primário.

26.2.5.1. Autenticação #

É muito importante que os privilégios de acesso para replicação sejam configurados de forma que apenas usuários confiáveis possam ler o fluxo de WAL, porque é fácil extrair informações privilegiadas dele. Os servidores em-espera devem ser autenticados no servidor principal com uma conta que possui o privilégio REPLICATION, ou ser superusuário. É recomendado criar uma conta de usuário dedicada para replicação, com os privilégios REPLICATION e LOGIN. Embora o privilégio REPLICATION forneça permissões muito altas, não permite que o usuário modifique nenhum dado no servidor primário, que o privilégio SUPERUSER permite.

A autenticação do cliente para replicação é controlada por um registro no arquivo pg_hba.conf especificando o pseudo banco de dados replication no campo database. Por exemplo, se o servidor em-espera estiver sendo executado no hospedeiro com endereço IP 192.168.1.100, e o nome da conta para replicação for foo, o administrador poderá adicionar a seguinte linha ao arquivo pg_hba .conf no servidor primário:

# Permitir o usuário "foo" se conectar ao servidor primário a partir do
# hospedeiro com IP 192.168.1.100 para replicação, se a senha do usuário
# for fornecida corretamente.
#
# TYPE  DATABASE        USER        ADDRESS                 METHOD
host    replication     foo         192.168.1.100/32        scram-sha-256

O nome do hospedeiro e o número da porta do servidor primário, o nome de usuário da conexão e sua senha são especificados em primary_conninfo. A senha também pode ser especificada no arquivo ~/.pgpass no servidor em-espera (especificando replication no campo database). Por exemplo, se o servidor primário estiver em execução no hospedeiro com endereço de IP 192.168.1.50, porta 5432, o nome da conta para replicação for foo, e a senha for foopass, o administrador poderá adicionar a seguinte linha ao arquivo postgresql.conf no servidor em-espera:

# O servidor em-espera se conecta ao servidor primário em execução no
# hospedeiro 192.168.1.50 e na porta 5432, como o usuário "foo" cuja
# senha é "foopass".
primary_conninfo = 'host=192.168.1.50 port=5432 user=foo password=foopass'

26.2.5.2. Monitoramento #

Um importante indicador de integridade da replicação por fluxo é a quantidade de registros de transação gerados no servidor primário, mas ainda não aplicados no servidor em-espera. Pode-se calcular este atraso comparando o local de escrita do WAL corrente no servidor primário, com o último local do WAL recebido pelo servidor em-espera. Estes locais podem ser obtidos usando a função pg_current_wal_lsn no servidor primário, e a função pg_last_wal_receive_lsn no servidor em-espera, respectivamente (veja a Tabela 9.97 e a Tabela 9.98 para obter detalhes). O último local de recebimento do WAL no servidor em-espera também está presente no status do processo de recepção de WAL, exibido usando o comando ps (veja Ferramentas padrão do Unix para obter detalhes).

Pode-se obter a lista de processos de envio de WAL por meio da visão pg_stat_replication. Diferenças grandes entre o que é mostrado pela função pg_current_wal_lsn e o campo sent_lsn dessa visão, podem indicar que o servidor primário está sob carga intensa, enquanto diferenças entre o campo sent_lsn e o que é mostrado pela função pg_last_wal_receive_lsn no servidor em-espera podem indicar atraso de rede, ou que o servidor em-espera está sob carga intensa.

No servidor em-espera ativo (Hot-Standby), o status do processo de recepção de WAL pode ser obtido por meio da visão pg_stat_wal_receiver. Uma grande diferença entre pg_last_wal_replay_lsn e o campo flushed_lsn dessa visão, indica que o WAL está sendo recebido mais rápido do que pode ser reproduzido.

26.2.6. Encaixes de replicação #

Os encaixes (slots) de replicação fornecem uma maneira automatizada de garantir que o servidor primário não remova segmentos de WAL até que tenham sido recebidos por todos os servidores em-espera, e que o servidor primário não remova linhas que possam causar conflito de restauração, mesmo quando o servidor em-espera estiver desconectado.

Em vez de usar encaixes de replicação, é possível impedir a remoção de segmentos do WAL antigos usando wal_keep_size, ou armazenando os segmentos no arquivamento usando archive_command ou archive_library. Uma desvantagem desses métodos é que eles frequentemente resultam na retenção de mais segmentos de WAL do que o necessário, enquanto os encaixes de replicação retêm apenas a quantidade de segmentos comprovadamente necessária.

Da mesma forma, hot_standby_feedback por si só, sem também usar encaixe de replicação, fornece proteção contra a remoção de linhas relevantes pelo processo de limpeza, mas não proporciona proteção durante qualquer período em que o servidor em-espera não esteja conectado.

Cuidado

Deve-se tomar cuidado, porque os encaixes de replicação podem fazer com que o servidor retenha tantos segmentos de WAL a ponto de ocuparem todo o espaço disponível para pg_wal. Pode ser usado max_slot_wal_keep_size para limitar o tamanho dos arquivos de WAL retidos pelos encaixes de replicação.

26.2.6.1. Consulta e manuseio de encaixes de replicação #

Cada encaixe de replicação tem um nome, que pode conter apenas letras minúsculas (sem acento), números, e o caractere de sublinhado.

Os encaixes de replicação existentes e seus estados podem ser consultados na visão pg_replication_slots.

Os encaixes podem ser criados e excluídos por meio do protocolo de replicação por fluxo (veja Seção 54.4), ou através de funções SQL (veja Funções de gerenciamento de replicação).

26.2.6.2. Exemplo de configuração #

Pode-se criar um encaixe de replicação da seguinte forma:

postgres=# SELECT *
postgres-# FROM pg_create_physical_replication_slot('ponto_de_encaixe_a');

     slot_name      | lsn
--------------------+-----
 ponto_de_encaixe_a |
(1 linha)

postgres=# SELECT slot_name, slot_type, active
postgres-# FROM pg_replication_slots;

     slot_name      | slot_type | active
--------------------+-----------+--------
 ponto_de_encaixe_a | physical  | f
(1 linha)

Para configurar o servidor em-espera para usar este encaixe, deve ser configurado primary_slot_name no servidor em-espera (arquivo postgresql.conf) A seguir está um exemplo simples:

primary_conninfo = 'host=192.168.1.50 port=5432 user=foo password=foopass'
primary_slot_name = 'ponto_de_encaixe_a'

26.2.7. Replicação em cascata #

Figura 26.6. Replicação em cascata


A funcionalidade de replicação em cascata permite que um servidor em-espera aceite conexões de replicação, e transmita registros de WAL para outros servidores em-espera, agindo como um retransmissor. Pode ser usado para reduzir o número de conexões diretas ao servidor primário, e também para minimizar as sobrecargas de largura de banda entre instalações.

Um servidor em-espera atuando tanto como receptor quanto como transmissor é conhecido como servidor em-espera em cascata. Os servidores em-espera que estejam mais diretamente conectados ao servidor primário são conhecidos como servidores upstream (rio acima/montante), enquanto os servidores em-espera mais distantes são os servidores downstream (rio abaixo/jusante). A replicação em cascata não impõe limites ao número ou a disposição dos servidores downstream, embora cada servidor em-espera se conecte a apenas um servidor upstream, que, por fim, se liga a um único servidor primário (nascente).

Um servidor em-espera em cascata envia não apenas os registros de WAL recebidos do servidor primário, mas também aqueles restaurados do arquivamento. Portanto, mesmo que seja fechada a conexão de replicação em alguma conexão upstream, a replicação por fluxo continuará downstream, enquanto novos registros de transação estiverem disponíveis.

No momento, a replicação em cascata é assíncrona. As configurações de replicação síncrona (veja Replicação síncrona) não têm efeito sobre a replicação em cascata no momento.

O retorno dos servidores Hot-Standby se propagam para os servidores upstream, independentemente da configuração em cascata

Se um servidor em-espera upstream for promovido para se tornar o novo servidor primário, os servidores downstream continuarão a transmitir do novo servidor primário, se recovery_target_timeline estiver definido como 'latest' (o padrão).

Para usar a replicação em cascata, deve-se configurar o servidor em-espera em cascata para poder aceitar conexões de replicação (ou seja, definir max_wal_senders e hot_standby, e configurar a autenticação baseada em hospedeiro). Também será necessário definir primary_conninfo no servidor em-espera downstream para apontar para o servidor em-espera em cascata.

26.2.8. Replicação síncrona #

Figura 26.7. Resumo dos diferentes níveis de segurança


A replicação por fluxo do PostgreSQL é assíncrona por padrão. Se o servidor primário falhar, algumas transações que foram efetivadas podem não ter sido replicadas para o servidor em-espera, causando perda de dados. A quantidade de dados perdidos é proporcional ao atraso da replicação no momento da comutação de servidores (failover).

A replicação síncrona oferece a capacidade de confirmar que todas as alterações feitas por uma transação foram transferidas para um ou mais servidores em-espera síncronos. Isto estende o nível padrão de durabilidade oferecido por uma efetivação de transação (commit). Na teoria da ciência da computação, este nível de proteção é referido como replicação 2-safe e group-1-safe (group-safe & 1-safe), quando synchronous_commit está definido como remote_write [149] [150] [151] [152].

Ao requisitar a replicação síncrona, cada efetivação de uma transação de escrita aguardará até que seja recebida a confirmação de que a efetivação foi escrita nos registros de transação no disco do servidor primário e do servidor em-espera. A única possibilidade de perda de dados é se o servidor primário e o servidor em-espera sofrerem falhas ao mesmo tempo. Pode fornecer um nível muito mais alto de durabilidade, embora apenas se o administrador do sistema for cauteloso quanto ao posicionamento e gerenciamento dos dois servidores. Esperar pela confirmação aumenta a confiança do usuário de que as alterações não serão perdidas em caso de queda do servidor, mas também necessariamente aumenta o tempo de resposta para a transação solicitante. O tempo de espera mínimo é o tempo de ida e volta entre o servidor primário e servidor em-espera.

As transações de leitura-apenas, e a reversão de transações (rollback), não precisam esperar por respostas de servidores em-espera. As efetivações de subtransação não esperam por respostas de servidores em-espera, apenas as efetivações de nível superior esperam. As ações de execução longa, como carregamento de dados ou criação de índice, não esperam pela mensagem de efetivação final. Todas as ações de efetivação de duas-fases requerem esperas de confirmação, incluindo a preparação e a efetivação.

Um servidor em-espera síncrono pode ser um servidor em-espera de replicação física, ou um subscritor de replicação lógica. Também pode ser qualquer outro consumidor de fluxo de replicação de registros de transação físico ou lógico, que saiba como enviar as mensagens de retorno apropriadas. Além dos sistemas nativos de replicação física e lógica, também se incluem programas especiais como pg_receivewal e pg_recvlogical, bem como alguns sistemas de replicação de terceiros e programas personalizados. Deve ser verificada a respectiva documentação para obter detalhes sobre suporte à replicação síncrona.

26.2.8.1. Configuração básica #

Após configurar a replicação por fluxo, a configuração da replicação síncrona requer apenas uma etapa de configuração adicional: o parâmetro synchronous_standby_names deve ser definido como um valor não vazio. O parâmetro synchronous_commit também deve ser definido como on, mas como este é o valor padrão, geralmente nenhuma alteração é necessária. (Veja Configurações e Servidor primário.) Esta configuração fará com que cada efetivação aguarde a confirmação de que o servidor em-espera escreveu o registro de efetivação no armazenamento durável. O parâmetro synchronous_commit pode ser definido para usuários individuais, portanto, pode ser configurado no arquivo de configuração, para usuários ou bancos de dados específicos, ou dinamicamente por aplicações, a fim de controlar a garantia de durabilidade por transação.

Após o registro de efetivação ter sido escrito em disco no servidor primário, o registro de transação é enviado para o servidor em-espera. O servidor em-espera envia uma mensagem de resposta cada vez que um novo lote de dados de registros de transação é escrito em disco, a menos que wal_receiver_status_interval seja definido como zero no servidor em-espera. Caso o parâmero synchronous_commit seja definido como remote_apply, o servidor em-espera enviará mensagem de resposta quando o registro de efetivação for aplicado, tornando a transação visível. Se o servidor em-espera for configurado como servidor em-espera síncrono, segundo a configuração de synchronous_standby_names no servidor primário, as mensagens de resposta desse servidor em-espera serão consideradas juntamente com as de outros servidores em-espera síncronos, para decidir quando liberar as transações que aguardam pela confirmação de que o registro de efetivação foi recebido. Estes parâmetros permitem que o administrador especifique quais servidores em-espera devem ser servidores em-espera síncronos. Note que a configuração da replicação síncrona se dá principalmente no servidor primário. Os servidores em-espera indicados devem ser conectados diretamente ao servidor primário; o servidor primário não sabe nada sobre os servidores em-espera downstream usando replicação em cascata.

Definir synchronous_commit como remote_write fará com que cada efetivação espere pela confirmação de que o servidor em-espera recebeu o registro de efetivação e o escreveu em seu próprio sistema operacional, mas não para que os dados sejam descarregados em disco no servidor em-espera. Esta configuração fornece uma garantia de durabilidade mais fraca do que on: o servidor em-espera pode perder os dados em caso de travamento do sistema operacional, embora não seja um travamento do PostgreSQL. No entanto, é uma configuração útil na prática, porque pode diminuir o tempo de resposta da transação. A perda de dados só poderá ocorrer se o servidor primário e o servidor em-espera travarem, e o banco de dados do servidor primário for corrompido ao mesmo tempo.

Definir synchronous_commit como remote_apply fará com que cada efetivação espere até que os servidores em-espera síncronos correntes relatem que aplicaram a transação, tornando-a visível para as consultas do usuário. Em casos simples, permite o balanceamento de carga sem inconsistência.

Normalmente, um sinal de desligamento rápido interrompe as transações em andamento em todos os processos do servidor. Entretanto, no caso de replicação assíncrona, o servidor não realizará um desligamento completo até que todos os registros de WAL tenham sido transferidos para os servidores em-espera conectados.

26.2.8.2. Múltiplos servidores em-espera síncronos #

A replicação síncrona oferece suporte a um ou mais servidores em-espera síncronos; as transações vão aguardar até que todos os servidores em-espera considerados síncronos confirmem o recebimento de seus dados. O número servidores em-espera síncronos que as transações devam esperar pelas respostas é especificado no parâmetro synchronous_standby_names. Este parâmetro também especifica a lista de nomes de servidores em-espera, e o método (FIRST e ANY) para a escolha dos servidores em-espera síncronos dentre os listados.

O método FIRST especifica uma replicação síncrona baseada em prioridade, fazendo com que as efetivações de transação aguardem até que seus registros de transação sejam replicados para o número solicitado de servidores em-espera síncronos escolhidos com base em suas prioridades. Os servidores em-espera cujos nomes aparecem no início da lista têm maior prioridade, e são considerados síncronos. Os demais servidores em-espera que apareçam depois nesta lista representam possíveis servidores em-espera síncronos. Se algum dos servidores em-espera síncronos correntes for desconectado por qualquer motivo, será substituído imediatamente pelo próximo servidor em-espera com prioridade mais alta.

Um exemplo de synchronous_standby_names para vários servidores em-espera síncronos baseado em prioridade é:

synchronous_standby_names = 'FIRST 2 (s1, s2, s3)'

Neste exemplo, se quatro servidores em-espera s1, s2, s3 e s4 estiverem em execução, os dois servidores em-espera s1 e s2 serão escolhidas como servidores em-espera síncronos, porque seus nomes aparecem no início da lista de nomes de servidores em-espera. O servidor em-espera s3 é um servidor em-espera síncrono potencial, assumindo a função de servidor em-espera síncrono quando s1 ou s2 falhar. O servidor em-espera s4 é um servidor em-espera assíncrono, porque seu nome não está na lista.

O método ANY especifica uma replicação síncrona baseada em quórum, fazendo com que as efetivações de transação aguardem até que seus registros de WAL sejam replicados para pelo menos o número indicado de servidores em-espera síncronos na lista.

Um exemplo de synchronous_standby_names para vários servidores em-espera síncronos baseado em quorum é:

synchronous_standby_names = 'ANY 2 (s1, s2, s3)'

Neste exemplo, se quatro servidores em-espera s1, s2, s3 e s4 estiverem em execução, as efetivações de transação vão aguardar por respostas de pelo menos dois servidores em-espera entre s1, s2 e s3. O servidor em-espera s4 é um servidor em-espera assíncrono, porque seu nome não está na lista.

O status de síncrono dos servidores em-espera pode ser visto através da visão pg_stat_replication.

26.2.8.3. Planejamento para desempenho #

A replicação síncrona geralmente requer servidores em-espera cuidadosamente planejados e organizados para garantir que as aplicações tenham um desempenho aceitável. A espera não utiliza recursos do sistema, mas os bloqueios de transação continuam sendo mantidos até que a transferência seja confirmada. Como resultado, o uso imprudente de replicação síncrona reduz o desempenho das aplicações de banco de dados devido ao aumento dos tempos de resposta e maior contenção.

O PostgreSQL permite ao desenvolvedor da aplicação especificar o nível de durabilidade a ser usado na replicação. Pode ser especificado para todo o sistema, mas também pode ser especificado para usuários ou conexões específicas, ou até mesmo para transações individuais.

Por exemplo, a carga de trabalho de uma aplicação pode consistir em: 10% das alterações são detalhes importantes do cliente, enquanto 90% das alterações são dados menos importantes, os quais a empresa pode sobreviver mais facilmente se forem perdidos, como mensagens de conversa entre usuários.

Com as opções de replicação síncrona especificadas no nível da aplicação (no servidor primário), pode-se oferecer replicação síncrona para as alterações mais importantes, sem afetar o desempenho da maior parte do processamento. As opções no nível da aplicação são uma ferramenta importante e prática para permitir os benefícios da replicação síncrona para aplicações de alto desempenho.

Deve-se considerar que a largura de banda da rede deve ser maior que a taxa de geração de dados de registro de transação.

26.2.8.4. Planejamento para alta disponibilidade #

O parâmetro synchronous_standby_names especifica o número e os nomes dos servidores em-espera síncronos pelos quais as efetivações de transação vão aguardar por respostas quando o parâmetro synchronous_commit estiver definido como on, remote_apply ou remote_write. As efetivações de transação podem nunca terminar, se qualquer um dos servidores em-espera síncrono falhar.

A melhor solução para alta disponibilidade é garantir que estejam presentes tantos servidores em-espera síncronos quanto solicitados. Isto pode ser obtido indicando vários servidores em-espera síncronos em potencial no parâmetro synchronous_standby_names.

Em uma replicação síncrona baseada em prioridade, os servidores em-espera cujos nomes aparecem no início da lista são usados como servidores em-espera síncronos. Os servidores em-espera listados depois desses assumirão a função de servidor em-espera síncrono, se um dos servidores em-espera síncrono corrente falhar.

Em uma replicação síncrona baseada em quórum, todos os servidores em-espera que apareçam na lista são usados como candidato para servidor em-espera síncrono. Mesmo que um deles falhe, os demais servidores em-espera continuarão desempenhando o papel de candidato a servidor em-espera síncrono.

Quando um servidor em-espera é conectado pela primeira vez ao servidor primário, ele ainda não estará devidamente sincronizado. Isto é descrito como modo catchup. Quando o atraso entre o servidor em-espera e o servidor primário chega a zero pela primeira vez, ele chega ao estado de streaming (fluxo) em tempo real. A duração da restauração (catch-up) pode ser longa imediatamente após a criação do servidor em-espera. Se o servidor em-espera for desligado, o período de atualização aumentará conforme o tempo que o servidor em-espera ficou inativo. O servidor em-espera só poderá se tornar um servidor em-espera síncrono após atingir o estado streaming. Este status pode ser consultado usando a visão pg_stat_replication.

Se o servidor primário reiniciar enquanto existirem efetivações aguardando por confirmação, estas transações em-espera serão marcadas como inteiramente efetivadas assim que o servidor primário for recuperado. Não há como ter certeza de que todos os servidores em-espera receberam todos os dados de WAL pendentes no momento da falha do servidor primário. Algumas transações podem não aparecer como efetivadas no servidor em-espera, mesmo que apareçam como efetivadas no servidor primário. A garantia oferecida é a de que a aplicação não receberá um reconhecimento explícito de efetivação bem-sucedida da transação, até que os dados de registro de transação sejam recebidos com segurança por todos os servidores em-espera síncronos.

Se realmente não for possível manter tantos servidores em-espera síncronos quanto solicitado, então deve-se diminuir o número de servidores em-espera síncronos que as transações efetivadas devam esperar por respostas contidos no parâmetro synchronous_standby_names (ou desativá-lo), e recarregar o arquivo de configuração no servidor primário.

Se o servidor primário estiver isolado dos servidores em-espera restantes, deve-se fazer a comutação (failover) para o melhor candidato entre estes outros servidores em-espera restantes.

Se for necessário recriar um servidor em-espera enquanto houver transações aguardando por efetivação, certifique-se que as funções pg_backup_start() e pg_backup_stop() sejam executadas em um contexto onde a variável synchronous_commit esteja definida como off, caso contrário estas solicitações aguardarão indefinidamente pelo aparecimento da instância em-espera.

26.2.9. Arquivamento contínuo em servidores em-espera #

Quando é usado o arquivamento contínuo de registros de transação no servidor em-espera, há dois cenários diferentes: o arquivamento de registros de transação pode ser compartilhado entre o servidor primário e o servidor em-espera, ou o servidor em-espera pode ter seu próprio arquivamento de WAL Se o servidor em-espera tiver seu próprio arquivamento de WAL, definir archive_mode como always, fará com que o servidor em-espera chame o comando de arquivamento para cada segmento de registro de transação que receber, seja por restauração do arquivamento, ou seja por replicação por fluxo. O arquivamento compartilhado pode ser gerido de forma semelhante ao não compartilhado, mas archive_command ou archive_library deve testar se o arquivo que está sendo arquivado já existe, e se o arquivo existente possui conteúdo idêntico. Isto requer mais atenção ao definir archive_command ou archive_library, porque deve tomar cuidado para não sobrescrever um arquivo existente com conteúdo diferente, e deve retornar sucesso se exatamente o mesmo arquivo for arquivado duas vezes. E tudo isto deverá ser feito livre de condições de concorrência, se dois servidores tentarem arquivar o mesmo arquivo ao mesmo tempo.

Se archive_mode estiver definido como on, o arquivador não será ativado durante a restauração ou no modo em-espera. Se o servidor em-espera for promovido, iniciará o arquivamento após a promoção, mas não arquivará nenhum arquivo de registros de transação ou histórico da linha do tempo que não tenha sido gerado por ele mesmo. Para obter uma série completa de arquivos de registro de transação no arquivamento, deve-se garantir que todos os registros de transação estejam arquivados, antes que cheguem ao servidor em-espera. Isto é inerentemente verdadeiro com o envio de registro de transação baseado em arquivamento, porque o servidor em-espera só pode restaurar arquivos encontrados no arquivamento, mas não se estiver ativada a replicação por fluxo. Quando o servidor não está no modo de restauração, não há diferença entre os modos on e always.



[149] 1-Safe: a transação é segura quando entregue e registrada em 1 réplica apenas. (N. T.)

[150] 2-Safe: a transação é segura quando entregue e registrada em todas as réplicas. (N. T.)

[151] Group-Safe: a transação é segura quando entregue a todas as réplicas. (N. T.)

[152] Wiesmann, M., Schiper, A. (2004). Beyond 1-Safety and 2-Safety for Replicated Databases: Group-Safety. In: Bertino, E., et al. Advances in Database Technology - EDBT 2004. EDBT 2004. Lecture Notes in Computer Science, vol 2992. Springer, Berlin, Heidelberg. https://doi.org/10.1007/978-3-540-24741-8_11