Seconds_Behind_Master non è un health check della replica
Seconds_Behind_Master può leggere zero su una replica ferma da un'ora. Come controllare davvero una replica MySQL o MariaDB: entrambi i thread, GTID, heartbeat.

La replica da cui fareste il ripristino vale qualcosa solo se è aggiornata, coerente e fuori dalla portata di un attaccante. La maggior parte del monitoraggio controlla un solo numero, il ritardo di replica, e quel numero può leggere zero su una replica che ha smesso di ricevere modifiche un'ora fa. Ecco come controllare una replica MySQL o MariaDB in modo che la risposta significhi qualcosa.
Il problema con la cifra del ritardo
Seconds_Behind_Master (o Seconds_Behind_Source sulle MySQL più recenti) è calcolato dal thread SQL della replica: la differenza tra il timestamp dell'evento che sta applicando e l'ora corrente. Non sa nulla degli eventi che non ha ricevuto.
Quindi se il thread I/O che preleva le modifiche dal primario è bloccato su una connessione TCP half open, il thread SQL finisce tutto ciò che ha già e riporta 0. La replica sembra perfetta. Nel frattempo ha smesso di muoversi. La cifra legge anche NULL quando la replica è ferma, e molti controlli trattano NULL come «nessun ritardo».
Controllo uno: entrambi i thread, e i campi di errore
Il primo test è noioso e coglie la maggior parte dei problemi:
SHOW SLAVE STATUS\G -- or SHOW REPLICA STATUS\G
Richiedete Slave_IO_Running: Yes e Slave_SQL_Running: Yes (i nomi Replica_ sulle MySQL più recenti), e richiedete che Last_IO_Error e Last_SQL_Error siano vuoti. Connecting sul thread I/O non è «in esecuzione», è una replica che non riesce a raggiungere la sua sorgente.
Impostate anche uno slave_net_timeout (o replica_net_timeout) breve insieme a MASTER_HEARTBEAT_PERIOD sul canale di replica. Il primario invia allora heartbeat quando è inattivo, e una connessione morta viene rilevata in secondi invece di attendere il timeout di rete predefinito.
Controllo due: confrontate le posizioni, non i timestamp
Con la replica GTID, ogni transazione committata ha un identificatore, e potete confrontare direttamente dove sta il primario con dove sta la replica.
Su MariaDB:
-- on the primary
SELECT @@gtid_binlog_pos;
-- on the replica
SELECT @@gtid_slave_pos;
Su MySQL, confrontate @@gtid_executed sui due lati, oppure chiedete direttamente alla replica se si è messa al passo con un insieme:
SELECT WAIT_FOR_EXECUTED_GTID_SET('<primary gtid_executed>', 5);
Quando la posizione del primario continua ad avanzare e quella della replica no, avete una replica in stallo, qualunque cosa dica la cifra del ritardo. Questo confronto è anche il modo in cui si conclude un reseed o un cutover: entrambi i lati devono concordare sulla stessa transazione prima che qualcuno dichiari finito.
Controllo tre: un heartbeat che scrivete voi
La misurazione più onesta del ritardo è una riga che il primario aggiorna con il proprio orologio, riletta sulla replica. pt-heartbeat del Percona Toolkit fa esattamente questo:
# 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>
Poiché la misurazione viaggia attraverso la replica stessa, un thread I/O rotto si manifesta come ritardo in crescita costante, che è ciò che volevate vedere fin dall'inizio. Una scrittura di prova sul primario seguita da una lettura sulla replica dà la stessa prova a mano, ed è il controllo di accettazione più rapido per una nuova replica.
Controllo quattro: i dati sono davvero gli stessi?
La replica può girare allegramente sopra dati che sono divergenti, dopo un'istruzione che si comporta diversamente sui due lati, una scrittura fatta per errore sulla replica, o un tipo di tabella che non replica in sicurezza. pt-table-checksum esegue checksum a blocchi sul primario e lascia che la replica li trasporti sulla replica, poi riporta le tabelle che differiscono:
pt-table-checksum --replicate=percona.checksums --no-check-binlog-format h=<primary>
Eseguitelo con una cadenza adatta al vostro volume di scritture, fuori dalle ore di punta. Impostate read_only = ON su ogni replica (e super_read_only = ON su MySQL) così che nulla, nemmeno lo strumento di un amministratore, possa scriverci per sbaglio.
Controllo cinque: in che direzione va la connessione
Questo non riguarda affatto il ritardo. Una replica è la vostra copia di ripristino, quindi dovrebbe essere il lato che si fa avanti. La replica apre la connessione di replica verso il primario; il primario non dovrebbe avere alcun percorso di rete verso la replica.
Testatelo invece di presumerlo. Dal primario:
nc -vz -w 3 <replica-address> 3306
Dovrebbe andare in timeout. Se si connette, un attaccante che possiede il vostro server di produzione può raggiungere anche la copia da cui pensate di ripristinare. Noi imponiamo la direzione sulle appliance firewall, non sugli host, e la dimostriamo a ogni costruzione.
Allertate sullo stato, non su ogni campione
Raccogliete tutto quanto sopra in un unico stato per replica: OK, LAGGING (oltre una soglia concordata) o BROKEN (un thread giù, un errore impostato, o la posizione GTID ferma mentre il primario avanza). Poi allertate solo quando lo stato cambia, compreso il ritorno 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
Eseguitelo ogni pochi minuti da un timer. Gli ingegneri ricevono un messaggio quando qualcosa cambia e uno quando si ripristina, non un flusso che imparano a ignorare. Il vero rischio con le repliche non è il ritardo; è una replica ferma da settimane senza che nessuno se ne sia accorto.
Reseed senza tirare a indovinare
Quando una replica ha davvero bisogno di essere ricostruita, il GTID elimina la caccia alle coordinate del binary log. Un dump logico consistente con la posizione incorporata, oppure un backup fisico con Mariabackup o Percona XtraBackup, vi dà la transazione esatta da cui ripartire. Su MariaDB il lato replica si riduce 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;
Poi rieseguite i controlli da uno a tre e non firmate finché entrambi i lati non riportano lo stesso GTID dopo una scrittura di prova.
La vostra checklist
- Entrambi i thread di replica in esecuzione, campi di errore vuoti, un periodo di heartbeat impostato sul canale.
- Posizioni GTID di primario e replica confrontate, non solo la cifra del ritardo.
- Una riga di heartbeat o una scrittura di prova che dimostri che le modifiche arrivano davvero.
- Checksum a calendario, e read_only su ogni replica.
- Il primario non può aprire una connessione verso la replica, dimostrato dal primario.
- Allarmi sui cambi di stato, così una replica in stallo è un messaggio entro minuti, non una scoperta il giorno in cui vi serve.
Se volete un secondo paio di occhi sulle vostre repliche, è il tipo di lavoro che ci piace.
Related (rows[1])
Correlati: Replica di database e repliche offsite · Database in cluster con Percona XtraDB Cluster · Migrazioni di datacenter gestite, provate in anticipo
Pubblicato il 8 ottobre 2026.
Tutte le note dal campo