Μετάβαση στο περιεχόμενο
EuroVPSEuroVPS
Περιοχή πελατών

Το Seconds_Behind_Master δεν είναι έλεγχος υγείας replica

Γιατί το replication lag από μόνο του μπορεί να λέει ότι ένα replica είναι εντάξει ενώ δεν είναι, και πώς ελέγχετε replicas MySQL και MariaDB με GTID, heartbeat, checksum και κατεύθυνση σύνδεσης.

Από EuroVPS Engineering

5 λεπτά ανάγνωσης
Seconds_Behind_Master is not a replica health check

Το replica από το οποίο θα κάνατε restore αξίζει κάτι μόνο αν είναι ενημερωμένο, συνεπές και εκτός εμβέλειας ενός επιτιθέμενου. Η περισσότερη παρακολούθηση ελέγχει έναν αριθμό, το replication lag, και αυτός ο αριθμός μπορεί να δείχνει μηδέν σε ένα replica που σταμάτησε να λαμβάνει αλλαγές πριν από μία ώρα. Να πώς ελέγχετε ένα replica MySQL ή MariaDB ώστε η απάντηση να σημαίνει κάτι.

Το πρόβλημα με τον αριθμό του lag

Το Seconds_Behind_Master (ή Seconds_Behind_Source σε νεότερη MySQL) υπολογίζεται από το SQL thread του replica: η διαφορά ανάμεσα στη χρονοσήμανση του συμβάντος που εφαρμόζει και την τρέχουσα ώρα. Δεν ξέρει τίποτα για συμβάντα που δεν έχει λάβει.

Οπότε αν το I/O thread που φέρνει αλλαγές από το primary έχει κολλήσει σε μια μισάνοιχτη σύνδεση TCP, το SQL thread τελειώνει ό,τι ήδη έχει και αναφέρει 0. Το replica μοιάζει τέλειο. Στο μεταξύ έχει σταματήσει να κινείται. Ο αριθμός δείχνει επίσης NULL όταν το replication είναι σταματημένο, και πολλοί έλεγχοι αντιμετωπίζουν το NULL ως «μηδέν lag».

Έλεγχος πρώτος: και τα δύο threads, και τα πεδία σφαλμάτων

Το πρώτο τεστ είναι βαρετό και πιάνει τα περισσότερα προβλήματα:

SHOW SLAVE STATUS\G      -- or SHOW REPLICA STATUS\G

Απαιτήστε Slave_IO_Running: Yes και Slave_SQL_Running: Yes (τα ονόματα Replica_ σε νεότερη MySQL), και απαιτήστε τα Last_IO_Error και Last_SQL_Error να είναι κενά. Το Connecting στο I/O thread δεν είναι «running», είναι ένα replica που δεν μπορεί να φτάσει την πηγή του.

Ορίστε επίσης ένα μικρό slave_net_timeout (ή replica_net_timeout) μαζί με MASTER_HEARTBEAT_PERIOD στο κανάλι replication. Το primary τότε στέλνει heartbeats όταν είναι αδρανές, και μια νεκρή σύνδεση εντοπίζεται σε δευτερόλεπτα αντί να περιμένετε να λήξει το προεπιλεγμένο timeout δικτύου.

Έλεγχος δεύτερος: συγκρίνετε θέσεις, όχι χρονοσημάνσεις

Με GTID replication, κάθε committed transaction έχει αναγνωριστικό, και μπορείτε να συγκρίνετε απευθείας πού βρίσκεται το primary με το πού βρίσκεται το replica.

Σε MariaDB:

-- on the primary
SELECT @@gtid_binlog_pos;
-- on the replica
SELECT @@gtid_slave_pos;

Σε MySQL, συγκρίνετε το @@gtid_executed και στις δύο πλευρές, ή ρωτήστε απευθείας το replica αν έχει φτάσει ένα σύνολο:

SELECT WAIT_FOR_EXECUTED_GTID_SET('<primary gtid_executed>', 5);

Όταν η θέση του primary συνεχίζει να προχωρά και του replica όχι, έχετε ένα κολλημένο replica, ό,τι κι αν λέει ο αριθμός του lag. Αυτή η σύγκριση είναι επίσης ο τρόπος που ολοκληρώνετε ένα reseed ή ένα cutover: και οι δύο πλευρές πρέπει να συμφωνούν στο ίδιο transaction πριν το πει κανείς τελειωμένο.

Έλεγχος τρίτος: ένα heartbeat που γράφετε εσείς

Η πιο ειλικρινής μέτρηση lag είναι μια γραμμή που το primary ενημερώνει με το δικό του ρολόι, διαβασμένη πίσω στο replica. Το pt-heartbeat από το Percona Toolkit κάνει ακριβώς αυτό:

# 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>

Επειδή η μέτρηση ταξιδεύει μέσα από το ίδιο το replication, ένα σπασμένο I/O thread εμφανίζεται ως σταθερά αυξανόμενο lag, που είναι αυτό που θέλατε να δείτε εξαρχής. Μια δοκιμαστική εγγραφή στο primary ακολουθούμενη από ανάγνωση στο replica δίνει την ίδια απόδειξη με το χέρι, και είναι ο γρηγορότερος έλεγχος αποδοχής για ένα νέο replica.

Έλεγχος τέταρτος: είναι τα δεδομένα πράγματι ίδια;

Το replication μπορεί να τρέχει μια χαρά πάνω από δεδομένα που έχουν αποκλίνει, μετά από ένα statement που συμπεριφέρεται διαφορετικά σε κάθε πλευρά, μια εγγραφή που έγινε στο replica κατά λάθος, ή έναν τύπο πίνακα που δεν αναπαράγεται με ασφάλεια. Το pt-table-checksum τρέχει checksums σε κομμάτια στο primary και αφήνει το replication να τα μεταφέρει στο replica, μετά αναφέρει τους πίνακες που διαφέρουν:

pt-table-checksum --replicate=percona.checksums --no-check-binlog-format h=<primary>

Τρέξτε το σε πρόγραμμα που ταιριάζει στον όγκο εγγραφών σας, εκτός αιχμής. Ορίστε read_only = ON σε κάθε replica (και super_read_only = ON σε MySQL) ώστε τίποτα, ούτε το εργαλείο ενός διαχειριστή, να μην μπορεί να γράψει σε αυτό κατά λάθος.

Έλεγχος πέμπτος: προς τα πού πάει η σύνδεση

Αυτός δεν αφορά καθόλου το lag. Ένα replica είναι το αντίγραφο ανάκαμψής σας, οπότε πρέπει να είναι η πλευρά που απλώνει το χέρι. Το replica ανοίγει τη σύνδεση replication προς το primary. Το primary δεν πρέπει να έχει καμία διαδρομή δικτύου προς το replica.

Δοκιμάστε το αντί να το υποθέσετε. Από το primary:

nc -vz -w 3 <replica-address> 3306

Αυτό πρέπει να λήξει χωρίς σύνδεση. Αν συνδεθεί, ένας επιτιθέμενος που κατέχει τον server παραγωγής σας μπορεί να φτάσει και το αντίγραφο από το οποίο σκοπεύετε να ανακάμψετε. Εμείς επιβάλλουμε την κατεύθυνση στις συσκευές firewall, όχι στους hosts, και το αποδεικνύουμε σε κάθε κατασκευή.

Ειδοποιήστε για την κατάσταση, όχι για κάθε δείγμα

Συγκεντρώστε όλα τα παραπάνω σε μία κατάσταση ανά replica: OK, LAGGING (πάνω από συμφωνημένο κατώφλι), ή BROKEN (thread κάτω, σφάλμα ορισμένο, ή θέση GTID παγωμένη ενώ το primary κινείται). Μετά ειδοποιήστε μόνο όταν αλλάζει η κατάσταση, μαζί με την επιστροφή σε 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

Τρέξτε το κάθε λίγα λεπτά από timer. Οι μηχανικοί λαμβάνουν ένα μήνυμα όταν κάτι αλλάζει και ένα όταν ανακάμπτει, όχι μια ροή που μαθαίνουν να αγνοούν. Ο πραγματικός κίνδυνος με τα replicas δεν είναι το lag. Είναι ένα replica που σταμάτησε πριν από εβδομάδες και κανείς δεν το πρόσεξε.

Reseed χωρίς μαντεψιές

Όταν ένα replica χρειάζεται πράγματι ξαναχτίσιμο, το GTID αφαιρεί το κυνήγι για συντεταγμένες binary log. Ένα συνεπές logical dump με ενσωματωμένη τη θέση, ή ένα physical backup με Mariabackup ή Percona XtraBackup, σας δίνει το ακριβές transaction από το οποίο ξεκινάτε. Σε MariaDB η πλευρά του replica περιορίζεται σε:

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;

Μετά τρέξτε ξανά τους ελέγχους ένα έως τρία και μην υπογράψετε μέχρι και οι δύο πλευρές να αναφέρουν το ίδιο GTID μετά από δοκιμαστική εγγραφή.

Η λίστα ελέγχου σας

  • Και τα δύο threads replication σε λειτουργία, πεδία σφαλμάτων κενά, heartbeat period ορισμένο στο κανάλι.
  • Θέσεις GTID primary και replica συγκρινόμενες, όχι μόνο ο αριθμός του lag.
  • Μια γραμμή heartbeat ή δοκιμαστική εγγραφή που αποδεικνύει ότι οι αλλαγές φτάνουν πράγματι.
  • Προγραμματισμένα checksums, και read_only σε κάθε replica.
  • Το primary δεν μπορεί να ανοίξει σύνδεση προς το replica, αποδεδειγμένο από το primary.
  • Ειδοποιήσεις σε αλλαγές κατάστασης, ώστε ένα κολλημένο replica να είναι ένα μήνυμα μέσα σε λεπτά, όχι μια ανακάλυψη τη μέρα που το χρειάζεστε.

Αν θέλετε ένα δεύτερο ζευγάρι μάτια στα replicas σας, αυτό είναι το είδος της δουλειάς που μας αρέσει.

Μιλήστε με έναν μηχανικό

Σχετικά: Database replication και offsite replicas · Βάσεις δεδομένων σε cluster με Percona XtraDB Cluster · Μεταφορές datacenter με διαχείριση, με πρόβα

Δημοσιεύθηκε 8 Οκτωβρίου 2026.

Όλες οι σημειώσεις