DevGuideTK
← Trilha Backend

Replicação

Cópias do banco para leitura e para tolerar falhas, e o atraso entre a principal e as réplicas.

O problema: um banco só é um ponto único de falha

Com um único servidor de banco, uma falha de disco, uma atualização do sistema operacional ou uma zona da nuvem fora do ar param o sistema inteiro. E todas as leituras, inclusive os relatórios pesados, disputam a mesma máquina com as gravações.

A replicação mantém cópias do banco em outras máquinas. Um servidor é o principal (primary), que recebe as gravações; os outros são réplicas, que recebem as alterações do principal. As réplicas servem para duas coisas:

  • Tolerar falhas: se o principal cair, uma réplica é promovida e passa a ser o novo principal.
  • Atender leituras: consultas que não precisam do dado mais recente vão para as réplicas.

O tópico do teorema CAP mostra o efeito mais visível da replicação: a janela em que a réplica ainda não tem a última gravação. Este tópico trata da mecânica, das escolhas e do que dá errado. Os testes usaram o PostgreSQL 18, com um principal e uma réplica.

Como a réplica acompanha o principal

Todo banco relacional grava cada alteração primeiro num log sequencial, o WAL (write-ahead log) no PostgreSQL, para se recuperar de quedas. A replicação reaproveita esse log: o principal envia o WAL às réplicas em fluxo contínuo, e cada réplica o aplica, na mesma ordem.

Cada posição no log tem um número crescente, o LSN (log sequence number). O principal sabe até onde gravou; cada réplica sabe até onde recebeu e até onde aplicou. A diferença é o atraso de replicação, visível em pg_stat_replication.

Síncrona ou assíncrona

A pergunta central é quando o principal confirma a gravação para a aplicação:

ModoO principal confirma quandoSe o principal cair logo depois
Assíncrono (padrão)Gravou no próprio discoA gravação pode não ter chegado à réplica
Síncrono (synchronous_commit = on)A réplica também gravou no discoA réplica tem a gravação
Síncrono com aplicação (remote_apply)A réplica gravou e aplicouA réplica tem a gravação, e uma leitura nela já a vê

O preço do síncrono é uma ida e volta até a réplica em cada COMMIT. Medimos com 5 ms de atraso de rede em cada sentido, gravando 200 linhas, cada uma confirmada sozinha:

synchronous_commitTempo por COMMIT
local (assíncrono para a réplica)6,5 ms
on18,3 ms
remote_apply18,6 ms

O tempo do assíncrono é quase só a ida e volta entre a aplicação e o principal. O síncrono somou a ida e volta até a réplica e a gravação no disco dela. Com a réplica em outra região, a centenas de quilômetros, cada COMMIT pagaria dezenas de milissegundos a mais.

O que se perde no assíncrono

Desconectamos a réplica da rede, gravamos 1.000 pedidos no principal, todos confirmados à aplicação, derrubamos o principal e promovemos a réplica:

Pedidos
Antes de desconectar a réplica602
No principal, depois das gravações1.602
Na réplica promovida602

As 1.000 gravações confirmadas sumiram. Para a aplicação, elas aconteceram: o cliente recebeu a confirmação do pedido. No novo principal, elas nunca existiram. Na prática, a réplica raramente fica tanto tempo desconectada, mas a janela é a mesma em escala menor: tudo o que o principal confirmou e ainda não tinha enviado no instante da queda se perde na troca.

O que trava no síncrono

O síncrono protege contra essa perda, e cobra de outro jeito. Com a réplica síncrona desconectada, um INSERT simples:

MomentoResultado
Depois de 5 segundos, com statement_timeout = 2sAinda esperando a réplica
A linha, vista por outra sessão no principalNão aparece
Ao cancelar a espera (pg_cancel_backend)A aplicação recebe sucesso

Três surpresas. O statement_timeout não interrompeu a espera pela réplica: as gravações ficaram paradas sem limite, enquanto a réplica estava fora. A linha, já gravada no disco do principal, ficou invisível para as outras sessões até a espera terminar. E, ao cancelar a espera, a aplicação recebeu confirmação, e não erro. O PostgreSQL só registrou um aviso no log: "The transaction has already committed locally, but might not have been replicated to the standby". A aplicação acha que a gravação está protegida, e ela está só no principal.

Por isso, quem usa replicação síncrona costuma ter duas ou mais réplicas e exigir a confirmação de qualquer uma delas (synchronous_standby_names = 'ANY 1 (r1, r2)'): uma réplica fora não trava as gravações.

O slot que enche o disco

Para não apagar o WAL que uma réplica ainda não recebeu, o principal usa slots de replicação: cada réplica tem um slot, e o principal guarda o WAL até ela confirmar. Se a réplica for desligada e o slot esquecido, o principal guarda o WAL para sempre.

Criamos um slot que nenhuma réplica usava e gravamos cerca de 1,5 GB de alterações:

Espaço do WAL no principal
Antes48 MB
Depois das gravações, com o slot abandonado2.544 MB, todos retidos pelo slot
Com max_slot_wal_keep_size = 256MB912 MB, e o slot marcado como perdido (lost)

Sem limite, o disco do principal enche até o banco parar. Com o limite, o principal se protege e descarta o slot; a réplica ligada a ele precisa ser recriada do zero. As duas saídas são melhores que a terceira: monitorar os slots e apagar os que não têm réplica.

Por que isso importa quando a IA escreve o código

Um assistente que configura réplicas e roteia as leituras costuma tratar a réplica como um espelho instantâneo:

  • Todas as leituras indo para a réplica, inclusive as que vêm logo depois de uma gravação.
  • Decisões de negócio (saldo, estoque, permissão) tomadas com dado lido da réplica.
  • Replicação assíncrona sem saber quanto pode ser perdido numa troca de principal.
  • Uma única réplica síncrona, que trava o sistema quando cai.
  • Slots de replicação sem monitoramento nem limite.
  • Promoção manual da réplica sem impedir que o principal antigo volte e aceite gravações (dois principais ao mesmo tempo).

O próximo nível compara as topologias de replicação e as formas de rotear leituras e trocar de principal.

Prompts para aprofundar

Ao abrir no ChatGPT ou no Claude, o prompt é enviado ao serviço escolhido pela URL e também fica copiado na sua área de transferência.

  • Replicação em cinco minutos

    Explique em no máximo cinco minutos de leitura o que é replicação de banco de dados, para alguém que só usou um banco num servidor.
    
    Cubra só o essencial: principal e réplicas, o log de alterações, replicação síncrona e assíncrona, o que se perde numa troca de principal e por que ler da réplica pode trazer dado velho.
    
    Use o exemplo de uma loja online com PostgreSQL. No final, me faça três perguntas curtas para eu verificar se entendi, e corrija as minhas respostas.
  • Síncrona, assíncrona e o que se perde

    Quero entender a fundo a diferença entre replicação síncrona e assíncrona.
    
    Aja como um mentor e vá por etapas, esperando a minha resposta em cada uma:
    1. O que o principal espera antes de confirmar o COMMIT em cada modo (local, remote_write, on, remote_apply).
    2. Uma linha do tempo de uma troca de principal no modo assíncrono, e o que se perde.
    3. O que acontece com as gravações quando a única réplica síncrona cai.
    4. Replicação síncrona com quórum e por que ela resolve o problema anterior.
    5. Como escolher o modo por transação.
    
    Em cada etapa, me dê um cenário e peça que eu diga o resultado.
  • Trocar de principal sem dois principais

    Quero entender como uma réplica assume o lugar do principal.
    
    Explique:
    1. A promoção de uma réplica e o que muda nela.
    2. A detecção automática de falha e por que ela precisa de consenso.
    3. O cérebro dividido: como dois principais acontecem e o estrago que causam.
    4. Como a aplicação encontra o principal novo.
    5. O que fazer com o principal antigo quando ele volta.
    
    Depois me descreva duas falhas e pergunte como a troca deveria acontecer em cada uma.
  • Ler da réplica sem mostrar dado velho

    Quero entender as formas de ler das réplicas sem confundir o usuário.
    
    Explique:
    1. Por que o usuário pode não ver o que acabou de gravar.
    2. Ler sempre do principal depois de gravar, por um tempo.
    3. Ler o que gravou com o LSN, e por que o LSN precisa ser lido depois do COMMIT.
    4. Replicação com remote_apply.
    5. Que leituras nunca devem ir para a réplica.
    
    Depois me dê quatro telas de um sistema e pergunte de onde cada uma deveria ler.