Seconds_Behind_Master не є перевіркою здоров’я репліки
Чому сама затримка реплікації може казати, що репліка в порядку, коли це не так, і як перевіряти репліки MySQL і MariaDB за GTID, heartbeat і контрольною сумою.

Репліка, з якої ви відновлювалися б, чогось варта лише тоді, коли вона актуальна, узгоджена і поза досяжністю зловмисника. Більшість моніторингів перевіряє одне число, затримку реплікації, а це число може показувати нуль на репліці, яка годину тому перестала отримувати зміни. Ось як перевіряти репліку MySQL або MariaDB так, щоб відповідь щось означала.
Проблема з показником затримки
Seconds_Behind_Master (або Seconds_Behind_Source у новіших MySQL) обчислює потік SQL репліки: різницю між міткою часу події, яку він застосовує, і поточним часом. Він нічого не знає про події, яких не отримав.
Тож якщо потік I/O, який забирає зміни з primary, застряг на напіввідкритому TCP-з’єднанні, потік SQL завершує все, що вже має, і повідомляє 0. Репліка виглядає ідеально. Тим часом вона перестала рухатися. Показник також читається як NULL, коли реплікацію зупинено, і багато перевірок трактують NULL як «без затримки».
Перевірка перша: обидва потоки і поля помилок
Перший тест нудний і ловить більшість проблем:
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 не є «працює», це репліка, яка не може дістатися до свого джерела.
Також задайте короткий slave_net_timeout (або replica_net_timeout) разом із MASTER_HEARTBEAT_PERIOD на каналі реплікації. Primary тоді надсилає heartbeat у простої, і мертве з’єднання виявляється за секунди замість чекати на стандартний мережевий таймаут.
Перевірка друга: порівнюйте позиції, а не мітки часу
З реплікацією GTID кожна закомічена транзакція має ідентифікатор, і ви можете напряму порівняти, де перебуває primary, з тим, де перебуває репліка.
На MariaDB:
-- on the primary
SELECT @@gtid_binlog_pos;
-- on the replica
SELECT @@gtid_slave_pos;
На MySQL порівняйте @@gtid_executed з обох боків або запитайте репліку напряму, чи наздогнала вона набір:
SELECT WAIT_FOR_EXECUTED_GTID_SET('<primary gtid_executed>', 5);
Коли позиція primary продовжує просуватися, а позиція репліки ні, у вас зупинена репліка, що б не казав показник затримки. Це порівняння також є тим, як ви завершуєте повторне засівання або cutover: обидві сторони мають погодитися на одній транзакції, перш ніж хтось назве це зробленим.
Перевірка третя: heartbeat, який ви пишете самі
Найчесніше вимірювання затримки є рядком, який primary оновлює власним годинником і який зчитується на репліці. 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>
Оскільки вимірювання подорожує через саму реплікацію, зламаний потік I/O проявляється як стабільно зростаюча затримка, що і є тим, що ви хотіли побачити від самого початку. Тестовий запис на primary з подальшим читанням на репліці дає той самий доказ вручну, і це найшвидша приймальна перевірка нової репліки.
Перевірка четверта: чи справді дані однакові?
Реплікація може щасливо працювати поверх даних, що розійшлися, після оператора, який поводиться по-різному з кожного боку, запису, помилково зробленого на репліці, або типу таблиці, який не реплікується безпечно. pt-table-checksum виконує контрольні суми частинами на primary і дозволяє реплікації перенести їх на репліку, а потім повідомляє таблиці, що відрізняються:
pt-table-checksum --replicate=percona.checksums --no-check-binlog-format h=<primary>
Запускайте його за розкладом, що відповідає вашому обсягу записів, поза піком. Задайте read_only = ON на кожній репліці (і super_read_only = ON на MySQL), щоб ніщо, включно з інструментом адміністратора, не могло випадково на неї писати.
Перевірка п’ята: в який бік іде з’єднання
Ця перевірка зовсім не про затримку. Репліка є вашою копією для відновлення, тож саме вона має бути стороною, яка ініціює. Репліка відкриває з’єднання реплікації до primary; primary не повинен мати жодного мережевого шляху до репліки.
Протестуйте це, а не припускайте. З primary:
nc -vz -w 3 <replica-address> 3306
Це має завершитися таймаутом. Якщо воно з’єднується, зловмисник, який володіє вашим робочим сервером, може дістатися і до копії, з якої ви плануєте відновлюватися. Ми забезпечуємо напрямок на firewall-пристроях, а не на хостах, і доводимо його на кожній збірці.
Тривога на стан, а не на кожен зразок
Зберіть усе вищенаведене в один стан на репліку: OK, LAGGING (понад узгоджений поріг) або BROKEN (потік лежить, встановлено помилку або позиція 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
Запускайте це кожні кілька хвилин з таймера. Інженери отримують одне повідомлення, коли щось змінюється, і одне, коли воно відновлюється, а не потік, який вони вчаться ігнорувати. Справжній ризик з репліками не в затримці; він у репліці, яка зупинилася тижні тому, і ніхто не помітив.
Повторне засівання без здогадок
Коли репліку справді треба відбудувати, GTID прибирає полювання за координатами бінарного лога. Узгоджений логічний дамп із вбудованою позицією або фізичний backup через Mariabackup або Percona XtraBackup дає вам точну транзакцію, з якої починати. На MariaDB боку репліки зводиться до:
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 після тестового запису.
Ваш чекліст
- Обидва потоки реплікації працюють, поля помилок порожні, на каналі задано період heartbeat.
- Позиції GTID primary і репліки порівняні, а не лише показник затримки.
- Рядок heartbeat або тестовий запис, що доводить, що зміни справді надходять.
- Контрольні суми за розкладом і
read_onlyна кожній репліці. - Primary не може відкрити з’єднання до репліки, доведено з primary.
- Тривоги на зміни стану, щоб зупинена репліка була повідомленням протягом хвилин, а не відкриттям у день, коли вона вам потрібна.
Якщо ви хочете другу пару очей на ваші репліки, це той вид роботи, який нам подобається.
Related (rows[1])
Пов’язане: Реплікація баз даних і віддалені репліки · Кластерні бази даних з Percona XtraDB Cluster · Міграції датацентрів з керуванням, відрепетирувані
Опубліковано 8 жовтня 2026 р..
Усі нотатки з практики