O Seconds_Behind_Master não é um health check da réplica
Porque é que o replication lag por si só pode dizer que uma réplica está bem quando não está, e como verificar réplicas MySQL e MariaDB com GTID, heartbeat, checksum e sentido da ligação.

A réplica a partir da qual faria um restore só vale alguma coisa se estiver atual, consistente e fora do alcance de um atacante. A maior parte da monitorização verifica um número, o replication lag, e esse número pode marcar zero numa réplica que deixou de receber alterações há uma hora. Eis como verificar uma réplica MySQL ou MariaDB de forma a que a resposta signifique alguma coisa.
O problema com o valor do lag
O Seconds_Behind_Master (ou Seconds_Behind_Source em MySQL mais recente) é calculado pelo SQL thread da réplica: a diferença entre o carimbo temporal do evento que está a aplicar e a hora atual. Não sabe nada sobre eventos que não recebeu.
Por isso, se o I/O thread que vai buscar as alterações ao primário estiver preso numa ligação TCP meio aberta, o SQL thread termina tudo o que já tem e reporta 0. A réplica parece perfeita. Entretanto, deixou de se mover. O valor também marca NULL quando a replicação está parada, e muitas verificações tratam o NULL como «sem lag».
Verificação um: os dois threads, e os campos de erro
O primeiro teste é aborrecido e apanha a maioria dos problemas:
SHOW SLAVE STATUS\G -- or SHOW REPLICA STATUS\G
Exija Slave_IO_Running: Yes e Slave_SQL_Running: Yes (os nomes Replica_ em MySQL mais recente), e exija que Last_IO_Error e Last_SQL_Error estejam vazios. Connecting no I/O thread não é «running», é uma réplica que não consegue chegar à sua fonte.
Defina também um slave_net_timeout curto (ou replica_net_timeout) juntamente com MASTER_HEARTBEAT_PERIOD no canal de replicação. O primário passa então a enviar heartbeats quando está inativo, e uma ligação morta é detetada em segundos em vez de se esperar pelo fim do timeout de rede predefinido.
Verificação dois: compare posições, não carimbos temporais
Com replicação GTID, cada transação confirmada tem um identificador, e pode comparar diretamente onde está o primário com onde está a réplica.
Em MariaDB:
-- on the primary
SELECT @@gtid_binlog_pos;
-- on the replica
SELECT @@gtid_slave_pos;
Em MySQL, compare @@gtid_executed dos dois lados, ou pergunte diretamente à réplica se já alcançou um conjunto:
SELECT WAIT_FOR_EXECUTED_GTID_SET('<primary gtid_executed>', 5);
Quando a posição do primário continua a avançar e a da réplica não, tem uma réplica parada, diga o valor do lag o que disser. Esta comparação é também a forma de terminar um reseed ou um cutover: os dois lados têm de concordar na mesma transação antes de alguém o dar por concluído.
Verificação três: um heartbeat escrito por si
A medição de lag mais honesta é uma linha que o primário atualiza com o seu próprio relógio, lida de volta na réplica. O pt-heartbeat do Percona Toolkit faz exatamente isso:
# on the primary, as a service
pt-heartbeat --update --database percona --create-table --daemonize
# on the replica, from monitoring
pt-heartbeat --check --database percona --master-server-id <id>
Como a medição viaja através da própria replicação, um I/O thread avariado aparece como lag a crescer de forma constante, que era o que queria ver desde o início. Uma escrita de teste no primário seguida de uma leitura na réplica dá a mesma prova à mão, e é a verificação de aceitação mais rápida para uma réplica nova.
Verificação quatro: os dados são mesmo iguais?
A replicação pode correr alegremente sobre dados que divergiram, depois de um statement que se comporta de forma diferente de cada lado, de uma escrita feita na réplica por engano, ou de um tipo de tabela que não replica em segurança. O pt-table-checksum corre checksums por blocos no primário e deixa a replicação transportá-los até à réplica, reportando depois as tabelas que diferem:
pt-table-checksum --replicate=percona.checksums --no-check-binlog-format h=<primary>
Corra-o num calendário adequado ao seu volume de escritas, fora das horas de pico. Defina read_only = ON em todas as réplicas (e super_read_only = ON em MySQL) para que nada, nem a ferramenta de um administrador, lhes possa escrever por acidente.
Verificação cinco: em que sentido vai a ligação
Esta não tem nada a ver com lag. Uma réplica é a sua cópia de recuperação, por isso deve ser o lado que estende a mão. A réplica abre a ligação de replicação para o primário; o primário não deve ter qualquer caminho de rede para a réplica.
Teste-o em vez de o presumir. A partir do primário:
nc -vz -w 3 <replica-address> 3306
Isto deve expirar sem ligação. Se ligar, um atacante que domine o seu servidor de produção também consegue chegar à cópia a partir da qual tenciona recuperar. Nós impomos o sentido nos equipamentos de firewall, não nos hosts, e provamo-lo em cada construção.
Alerte pelo estado, não por cada amostra
Reúna tudo o que está acima num único estado por réplica: OK, LAGGING (acima de um limiar acordado) ou BROKEN (um thread em baixo, um erro definido, ou a posição GTID congelada enquanto o primário avança). Depois alerte apenas quando o estado muda, incluindo o regresso a OK.
state=$(replica_state) # your check, returns OK, LAGGING or BROKEN
last=$(cat /var/lib/replcheck/state 2>/dev/null)
if [ "$state" != "$last" ]; then
notify "replica: $last -> $state"
echo "$state" > /var/lib/replcheck/state
fi
Corra-o a cada poucos minutos a partir de um timer. Os engenheiros recebem uma mensagem quando algo muda e outra quando recupera, não um fluxo que aprendem a ignorar. O verdadeiro risco com as réplicas não é o lag; é uma réplica que parou há semanas e ninguém reparou.
Reseed sem adivinhações
Quando uma réplica precisa mesmo de ser reconstruída, o GTID elimina a caça às coordenadas do binary log. Um dump lógico consistente com a posição embutida, ou um backup físico com Mariabackup ou Percona XtraBackup, dá-lhe a transação exata a partir da qual começar. Em MariaDB o lado da réplica reduz-se a:
SET GLOBAL gtid_slave_pos = '<position from the dump or backup>';
CHANGE MASTER TO MASTER_HOST='<primary>', MASTER_USER='repl',
MASTER_PASSWORD='<secret>', MASTER_USE_GTID=slave_pos;
START SLAVE;
Depois volte a correr as verificações um a três e não dê o trabalho por fechado até os dois lados reportarem o mesmo GTID após uma escrita de teste.
A sua lista de verificação
- Os dois threads de replicação em execução, campos de erro vazios, um heartbeat period definido no canal.
- Posições GTID do primário e da réplica comparadas, não apenas o valor do lag.
- Uma linha de heartbeat ou uma escrita de teste que prove que as alterações chegam mesmo.
- Checksums agendados, e
read_onlyem todas as réplicas. - O primário não consegue abrir uma ligação para a réplica, provado a partir do primário.
- Alertas nas mudanças de estado, para que uma réplica parada seja uma mensagem em minutos, não uma descoberta no dia em que precisa dela.
Se quiser um segundo par de olhos sobre as suas réplicas, este é o tipo de trabalho de que gostamos.
Relacionados: Replicação de bases de dados e réplicas offsite · Bases de dados em cluster com Percona XtraDB Cluster · Migrações de datacenter geridas, ensaiadas
Publicado em 8 de outubro de 2026.
Todas as notas de campo