Реплікація MariaDB vs Percona Server: коли крайні випадки підводять

Було корисно?

На діаграмах реплікація виглядає як пряма лінія: первинка пише, репліки слідують, усі йдуть додому.
У продакшні це місце злочину: репліка, яка «працює», але дає неправильні дані, фейловер, що «спрацював», але втратив дані,
або графік затримки, який йде в нуль саме тоді, коли CEO робить демонстрацію.

MariaDB та Percona Server обидва говорять «MySQL‑подібною» мовою, але їхні краєві випадки реплікації не завжди збігаються.
Найгірші відмови виникають від припущення, що вони це роблять. Це польовий довідник по гострих кутах: GTID, бінлоги,
стійкість до краху, фільтри, напівсинхронність і операційні звички, які не пустять вас у пекло постінцидентного огляду.

Що ви насправді обираєте (підказка: операційна семантика)

«MariaDB vs Percona Server» звучить як перевірка списку функцій. Реплікація робить це вибором поведінки.
У звичайні часи обидва будуть стримити binlog‑події до реплік і застосовувати їх. Під навантаженням — розриви мережі,
затримки диска, фейловери, відновлення після краху — різниця проявляється в тому: що записується в binlog, що підтверджується,
що вважається безпечним і що передбачає ваше інструментарій.

Percona Server — це варіант MySQL, який зазвичай близько відслідковує поведінку Oracle MySQL, додаючи інструментацію,
регулювання і операційні патчі (часто орієнтовані на продуктивність або видимість). MariaDB — це власний форк із
функціями реплікації, які інколи попереду, інколи просто відрізняються і часом несумісні в тонких моментах — особливо навколо семантики GTID.

Ось упереджене формулювання, що тримає в часи відмов:

  • Якщо вам потрібна сумісність із екосистемою MySQL перш за все, Percona Server зазвичай безпечніший вибір. Багато інструментів очікують GTID та деталі binlog у стилі Oracle.
  • Якщо ви хочете специфічні функції MariaDB (і готові прийняти семантику MariaDB), дотримуйтеся її повністю: використовуйте MariaDB GTID наскрізь, інструменти, що розуміють MariaDB, і регулярно тестуйте шляхи фейловера так само, як тестуєте бекапи.
  • Якщо плануєте змішувати MariaDB і Percona в одній топології реплікації, робіть це лише з письмовою матрицею сумісності й лабораторією, яка програє ваші реальні binlog‑файли. «Працювало один раз» — не матриця.

Історичні факти, що пояснюють сучасну дивність

Це короткі, конкретні історичні шматки, що мають значення, бо «дивність» реплікації зазвичай — це «спадок рішень,
прийнятих публічно». Тримайте це в голові під час налагодження.

  1. Реплікація MySQL починалася як statement‑based replication (SBR), що було крихким при недетермінованих запитах; row‑based replication (RBR) з’явилася пізніше і змінила експлуатаційні очікування.
  2. MariaDB відокремилася від MySQL у 2009 році і розвивала функції реплікації незалежно, включаючи власну реалізацію GTID і метадані.
  3. GTID Oracle MySQL (5.6+) і GTID MariaDB — це не той самий протокол; вони вирішують схожі проблеми з різними ідентифікаторами та правилами фейловера.
  4. Percona Server історично постачав «операторські» патчі — кращу інструментацію і регулювання; це вплинуло на те, як команди моніторять реплікацію (і що вони очікують бачити).
  5. MySQL 5.7/8.0 зробили row‑based реплікацію де‑факто стандартом у багатьох середовищах, бо вона зменшила «дрейф реплік», але підвищила обсяг binlog та чутливість до IO.
  6. Багатопотокова реплікація приходила поетапно: спочатку груба паралельність, потім більш дрібна «логічна годинникова»/GTID‑орієнтована паралельна аплікація в варіантах MySQL; MariaDB має власний підхід і регулювання паралельної реплікації.
  7. Напівсинхронна реплікація з’явилася як плагін і еволюціонувала; вона зменшує, але не усуває ризики втрати даних у певних послідовностях фейловера.
  8. Crash‑safe реплікація покращувалася з часом через репозиторії метаданих і відновлення relay log, але налаштування все ще можуть повернути вас у 2012 рік.
  9. Контрольні суми та метадані подій binlog зростали з часом; крос‑версійна та крос‑флейворна реплікація може ламатись через дрібниці, наприклад «binlog вказує CRC32, а репліка не погоджується».

Моделі реплікації та де MariaDB і Percona розходяться

Асинхронна реплікація: за замовчуванням, що ввічливо бреше

Класична асинхронна реплікація означає, що первинка фіксує транзакцію і відразу відповідає клієнту «OK», не чекаючи реплік.
Це швидко. Це також чесно щодо одного: якщо первинка помре, ви можете втратити останні транзакції.
Краєві випадки виникають, коли люди забувають, що ACK від сервера — не гарантія надійності за межами налаштувань первинного сховища.

Різниця між MariaDB і Percona тут не філософська. Вона в деталях:
як відстежується стан GTID, як відновлення після краху пересуває relay log, які значення за замовчуванням постачаються і що припускають ваші інструменти оркестрації.

Row vs statement vs mixed: формат реплікації — це не вподобання

Якщо ви досі використовуєте statement‑based реплікацію в критичних системах, ви по суті ставите на карту свою роботу щодо кожного запиту, що має бути детермінованим за всіма планами виконання, часовими зонами, SQL‑модами та семантикою функцій.
Це сміливий стиль життя.

RBR безпечніший щодо коректності, але важчий по диску, IO та інколи мережі. Mixed намагається бути розумним і часто підводить вас о 3‑й ранку. Важливий краєвий випадок: один недетермінований запит може спричинити дрейф репліки,
і тоді кожен «успішний» фейловер просто швидше переключає на неправельну базу.

Percona Server vs MariaDB: що відчувають оператори

Операторам байдуже до слоганів; їм важливо, чи роблять інструменти фейловера правильні вибори.
У Percona Server (що відслідковує семантику Oracle MySQL) GTID і внутрішні механіки реплікації зазвичай поводяться так, як очікує широка екосистема MySQL. Функції реплікації MariaDB можуть бути відмінними, але не завжди «drop‑in» сумісні.

Переклад: обидва варіанти можна налаштувати правильно, але не імпровізуйте. Реплікація карає самодіяльність.

GTID: найбільша «нога‑вистріл» з найкращим маркетингом

GTID мають зробити фейловер банальним: кожна транзакція має глобальний ідентифікатор, репліки знають, що вони виконали,
і ви можете підняти репліку без ручного підрахунку позицій у binlog.

Краєві випадки виникають через дві речі:

  • GTID MariaDB і GTID Oracle/MySQL — різні системи з різними форматами і відстеженням стану.
  • Коректність GTID залежить від того, як ви налаштували логування, стійкість до краху і від припущень вашого інструментарію фейловера.

GTID MariaDB vs MySQL/Percona GTID: «той самий акронім, інший контракт»

У MySQL/Percona‑стилі GTID UUID сервера (або набір ідентифікаторів) закладений у GTID‑сетах та статусних змінних, таких як gtid_executed. MariaDB використовує GTID на основі доменів з іншими змінними та конвенціями.
Обидві можуть підтримувати поведінку «auto‑positioning», але на рівні дроту та метаданих вони не взаємозамінні.

Змішування флейворів через GTID‑кордони — місце, де команди кровоточать. Якщо ви реплікуєте з MariaDB на Percona або навпаки, потрібно перевірити:

  • Чи підтримується GTID у цьому напрямку та поєднанні версій.
  • Чи розуміє канал реплікації формат GTID, який емулює первинка.
  • Чи читає ваш інструмент фейловера правильні статусні змінні і інтерпретує їх коректно.

GTID‑фейловер: що означає «безпечно» насправді

«Безпечний» GTID‑фейловер вимагає двох умов:

  1. Кандидат‑репліка отримала всі транзакції, що були підтверджені клієнтам (або ваш додаток погоджується втратити частину даних).
  2. Кандидат‑репліка застосувала ці транзакції і не перевиконає або не пропустить їх після підвищення.

GTID допомагає з умовою №2 (щоб не перевиконувати транзакції) якщо все налаштовано правильно. Він не гарантує №1. Тут важливі напівсинхронність, налаштування стійкості (sync_binlog, innodb_flush_log_at_trx_commit) і мережеві затримки.

Жарт №1

GTID — це як підписувати залишки їжі: все одно треба покласти їх у холодильник, якщо не хочеш жалкувати пізніше.

Сумісність binlog: контрольні суми, формати та мовчазні невідповідності

Реплікація в кінці кінців — це контракт: «я писатиму події так; ти їх зрозумієш і виконаєш».
Контракти ламаються трьома шляхами: первинка змінює те, що пише, репліка змінює те, що розуміє,
або проміжний пристрій тихо редагує трафік (рідко, але бували «допоміжні» проксі з дурними поведінками).

Контрольні суми binlog: маленьке налаштування, велика аварія

Контрольні суми binlog захищають від корупції, але сумісність залежить від узгодженості на обох кінцях.
Класичний режим відмови — оновлення однієї сторони або зміна значення за замовчуванням, після чого реплікація зупиняється з помилкою парсингу.

Практична порада: стандартизувати налаштування контрольних сум binlog по всьому флоту і зробити це частиною базового аудиту.
Не дозволяйте одній машині бути «особливою».

Формат binlog: RBR безпечніший, але слідкуйте за затримкою через обсяг

Коли ви переходите на RBR, зазвичай ви вирішуєте питання коректності й одночасно створюєте нові вузькі місця з продуктивності:
репліки стають I/O‑вузькими при застосуванні великих образів рядків, і relay log роздувається.

Percona Server і MariaDB обидва підтримують RBR, але їхня паралельна аплікація і параметри налаштування відрізняються.
Краєвий випадок тут не «чи може реплікуватись», а «чи може надолужити під час пікових записів та змін схеми».

Типи подій і версійний розрив

Крос‑версійна реплікація (навіть в межах одного флейвора) — це місце, де з’являються дивні типи подій.
Нова первинка може емутувати події, які трохи старша репліка не вміє парсити. Іноді ви отримуєте чисту помилку. Іноді це виглядає як затримка, потім стоп, а потім оператор у відчаї запускає START SLAVE як спосіб впоратись.

Напівсинхронність і сценарії «все одно втрата даних»

Напівсинхронна реплікація зменшує вікно втрати, чекаючи, поки принаймні одна репліка підтвердить отримання транзакції перед тим, як первинка відповість OK клієнту. Підтвердження — отримання, не застосування. Якщо підтверджена репліка має подію у relay log, але її ще не зафіксувала, при фейловері ви все одно можете її втратити — або, ще гірше, отримати розгалуження історії залежно від процедури.

Тут багато керівників чують «напівсинхронність» і думають «без втрати даних». Це уява, яка спричинила не одну напружену зустріч з фінансами.

Що насправді дає напівсинхронність

  • Менше транзакцій, підтверджених лише на первинці.
  • Кращі шанси, що підвищена репліка містить останні зафіксовані записи.
  • Більша затримка і більша чутливість до коливань реплік/мережі.

Послідовність відмов, що все ще втрачає дані

Первинка фіксує, відправляє репліці, репліка ACK підтверджує отримання, первинка відповідає клієнту. Потім репліка падає до застосування,
або relay log корумповано, або фейловер підвищує іншу репліку, яка ніколи не отримувала цю подію. Вітаємо:
напівсинхронний, асинхронний результат.

Ставлення оператора

Використовуйте напівсинхронність, якщо ваш бюджет латентності дозволяє це і ви розумієте її гарантії. Поєднуйте її з правилами підвищення:
підвищувати лише ті репліки, які підтверджено наздогнали і є достатньо стійкими для вашого RPO.
Інакше ви сплачуєте плату за латентність тільки за відчуття безпеки.

Паралельна реплікація: швидше, поки не стане ні

Паралельна реплікація — це функція продуктивності, яка перетворюється на дебати про коректність щойно з’являються крос‑схемні транзакції, «гарячі» рядки або робочі навантаження, які «переважно паралельні, окрім частин, що важливі».

Краєвий випадок: ви «оптимізуєте затримку», збільшуючи кількість воркерів, але репліка стає CPU‑зв’язана, або блокується мютексами,
або починає інтенсивно перезаписувати буфер пул, і застосування сповільнюється. Або вона встигає — поки не приходить DDL і все не накопичується за ним, як автомобілі за парадом.

Percona Server (узгоджений з MySQL) зазвичай використовує механіку паралельного аплаю в стилі MySQL і інструментацію, яку очікують багато інструментів.
MariaDB має власну систему паралельної реплікації і змінні, і шаблони налаштування не завжди переносимі. Треба вимірювати, а не вгадувати.

Фільтри та зміни схеми: повільні катастрофи

Фільтри реплікації (replicate-do-db, replicate-ignore-db, шаблони, фільтри таблиць)
здаються акуратним способом «зберегти лише потрібне». Насправді це довгострокове зобов’язання, якщо ви не ставите їх
у код: перевірені, тестовані й повторно перевірені після кожної зміни схеми.

Фільтри + змішаний формат binlog + крос‑базові запити можуть змусити репліки пропускати зміни мовчки.
«Мовчить» — найгірше слово у реплікації.

Реплікація DDL: де «вона працювала в staging» помирає

DDL жорсткий для реплік. Він часто однопотоковий, блокує і може створювати величезні події зміни рядків.
Інструменти онлайн‑змін схеми зменшують вплив, але вводять свої крайні випадки: тригери, фантомні таблиці й сплески затримки.

Якщо треба вибрати філософію: віддавайте пріоритет коректності й передбачуваному відновленню замість пікової пропускної здатності.
Ви можете купити обладнання для пропускної здатності. Ви не купите шлях із консистентними даними після поганого фейловера.

Практичні завдання: команди, виводи та рішення

Нижче наведені реальні операційні завдання. Кожне містить команду, приклад виводу, що це означає, і яке рішення ви приймаєте.
Використовуйте їх як м’язову пам’ять під час інцидентів і у звичайні вівторки при аудиті. Саме в нудні вівторки ви перемагаєте.

Завдання 1: Визначте флейвор і версію сервера (припиніть гадати)

cr0x@server:~$ mysql -e "SELECT @@version, @@version_comment\G"
*************************** 1. row ***************************
@@version: 10.11.6-MariaDB-1:10.11.6+maria~ubu2204
@@version_comment: MariaDB Server

Що це означає: Ви на MariaDB 10.11.x. Якщо ваш рукопис очікує змінні GTID у стилі MySQL/Percona, він вже неправильний.

Рішення: Використовуйте синтаксис/змінні реплікації MariaDB і переконайтеся, що ваш інструмент фейловера підтримує GTID MariaDB (якщо увімкнено).

Завдання 2: Перевірте binlog і налаштування стійкості первинки

cr0x@server:~$ mysql -e "SHOW VARIABLES WHERE Variable_name IN ('log_bin','binlog_format','sync_binlog','innodb_flush_log_at_trx_commit')"
+--------------------------------+-------+
| Variable_name                  | Value |
+--------------------------------+-------+
| binlog_format                  | ROW   |
| innodb_flush_log_at_trx_commit | 1     |
| log_bin                        | ON    |
| sync_binlog                    | 1     |
+--------------------------------+-------+

Що це означає: Binlog увімкнено, використовується row‑based формат, і стійкість жорстка (вищі IO‑витрати, краща стійкість після краху).

Рішення: Якщо затримка прийнятна, залишайте так. Якщо вас тягне послабити це, робіть це лише з явним погодженням RPO/RTO і протестованим планом відновлення.

Завдання 3: Підтвердіть статус репліки (нудний базовий контроль)

cr0x@server:~$ mysql -e "SHOW SLAVE STATUS\G" | egrep "Slave_IO_Running|Slave_SQL_Running|Seconds_Behind_Master|Last_SQL_Error|Last_IO_Error"
Slave_IO_Running: Yes
Slave_SQL_Running: Yes
Seconds_Behind_Master: 0
Last_IO_Error:
Last_SQL_Error:

Що це означає: Треди працюють і репліка стверджує, що немає затримки. Це необхідна, але не достатня умова коректності.

Рішення: Якщо ви діагностуєте «неправильні результати», потрібно йти далі і перевіряти виконані GTID / позиції / контрольні суми.

Завдання 4: Вимірюйте затримку реплікації правильно (не поклоняйтесь Seconds_Behind_Master)

cr0x@server:~$ pt-heartbeat --check --database=percona --table=heartbeat --host=127.0.0.1 --user=monitor --password='***'
0.183

Що це означає: Фактична спостережувана затримка ≈183ms. Це зазвичай надійніше, ніж Seconds_Behind_Master під навантаженням або при паралельній аплікації.

Рішення: Використовуйте heartbeat‑заміри для алертів та як умову фейловера. Ставтеся до Seconds_Behind_Master як до підказки, а не до оракула істини.

Завдання 5: Перевірте сумісність контрольних сум binlog

cr0x@server:~$ mysql -e "SHOW VARIABLES LIKE 'binlog_checksum';"
+-----------------+-------+
| Variable_name   | Value |
+-----------------+-------+
| binlog_checksum | CRC32 |
+-----------------+-------+

Що це означає: Первинка емулює CRC32‑контрольні суми. Репліка, що очікує NONE (або не має підтримки), може не змогти читати події.

Рішення: Переконайтеся, що репліки налаштовані для розуміння того самого режиму контрольних сум; стандартизуйте це по флоту перед оновленнями.

Завдання 6: Помітити тиск на relay log і ризик диска

cr0x@server:~$ du -sh /var/lib/mysql/*relay* 2>/dev/null | tail -n 3
18G	/var/lib/mysql/relay-bin.000112
18G	/var/lib/mysql/relay-bin.000113
36G	/var/lib/mysql/relay-log.info

Що це означає: Relay log великі. Це зазвичай корелює з затримкою або повільним застосуванням SQL‑потоком.

Рішення: Перш ніж перезапускати щось, знайдіть вузьке місце застосування (I/O, блокування, DDL). Якщо диск майже заповнений, пріоритезуйте зупинку витоку: обмежте записи, додайте місце або створіть нову репліку.

Завдання 7: Знайдіть поточні координати реплікації (позиція в binlog все ще важлива)

cr0x@server:~$ mysql -e "SHOW MASTER STATUS\G"
*************************** 1. row ***************************
File: mysql-bin.001874
Position: 918273645
Binlog_Do_DB:
Binlog_Ignore_DB:
Executed_Gtid_Set:

Що це означає: У вас є файл binlog/позиція. Навіть з GTID це корисно для точкового порівняння і налагодження.

Рішення: Запишіть це перед ризикованими операціями (фейловер, перезапуск, зміна конфігурації). Це ваш слід хлібних крихт, коли ви втомлені.

Завдання 8: Перевірте, чи репліка застосовує паралельно (і чи це допомагає)

cr0x@server:~$ mysql -e "SHOW VARIABLES LIKE 'slave_parallel_workers';"
+------------------------+-------+
| Variable_name          | Value |
+------------------------+-------+
| slave_parallel_workers | 16    |
+------------------------+-------+

Що це означає: Репліка налаштована на 16 паралельних воркерів (назва змінної в стилі MySQL/Percona; MariaDB використовує інші параметри залежно від версії).

Рішення: Якщо затримка погіршилась після збільшення воркерів, відкотіть зміни і профілюйте: насичення CPU, очікування мютексів, I/O‑застої та серіалізація DDL — часті винуватці.

Завдання 9: Проінспектуйте стани воркерів реплікації, щоб знайти блокер

cr0x@server:~$ mysql -e "SELECT THREAD_ID,PROCESSLIST_STATE,PROCESSLIST_INFO FROM performance_schema.threads t JOIN performance_schema.processlist p ON t.PROCESSLIST_ID=p.ID WHERE p.COMMAND IN ('Connect','Binlog Dump GTID','Binlog Dump','Query') LIMIT 5\G"
*************************** 1. row ***************************
THREAD_ID: 82
PROCESSLIST_STATE: Waiting for master to send event
PROCESSLIST_INFO: NULL
*************************** 2. row ***************************
THREAD_ID: 109
PROCESSLIST_STATE: Waiting for handler commit
PROCESSLIST_INFO: INSERT INTO orders ...

Що це означає: IO‑тред бездіяльний (добре), але воркер застряг, чекаючи на commit — часто із‑за I/O, fsync або контенції.

Рішення: Дивіться на затримки диска і тиск на InnoDB log flush. Не просто додавайте воркерів; ви лише помножите контенцію.

Завдання 10: Перевірте затримки диска (затримка реплікації часто — затримка сховища)

cr0x@server:~$ iostat -x 1 3
Device            r/s     w/s   r_await   w_await  aqu-sz  %util
nvme0n1         120.0   980.0     1.10    18.70    7.42   92.0

Що це означає: Записи чекають ≈19мс в середньому і пристрій завантажений ≈92%. SQL‑потік репліки ймовірно обмежений I/O.

Рішення: Зменште ампліфікацію записів (налаштування buffer pool, розмір логів), перемістіть репліки на швидше сховище або тимчасово знизьте швидкість записів. Налаштування CPU проблему насиченого диска не вирішить.

Завдання 11: Підтвердіть налаштування crash‑safe відновлення relay log

cr0x@server:~$ mysql -e "SHOW VARIABLES WHERE Variable_name IN ('relay_log_recovery','master_info_repository','relay_log_info_repository');"
+-------------------------+-------+
| Variable_name           | Value |
+-------------------------+-------+
| master_info_repository  | TABLE |
| relay_log_info_repository | TABLE |
| relay_log_recovery      | ON    |
+-------------------------+-------+

Що це означає: Метадані зберігаються в таблицях і relay log recovery увімкнено — добре для стійкості при краху.

Рішення: Якщо у флоті це FILE/OFF, заплануйте контрольовану зміну. День після некоректного перезавантаження — не час дізнаватись, що ви не можете відновити relay log коректно.

Завдання 12: Виявити злам реплікації через duplicate key (класика після неправильного підвищення)

cr0x@server:~$ mysql -e "SHOW SLAVE STATUS\G" | egrep "Last_SQL_Errno|Last_SQL_Error|Slave_SQL_Running"
Slave_SQL_Running: No
Last_SQL_Errno: 1062
Last_SQL_Error: Error 'Duplicate entry '1842' for key 'PRIMARY'' on query. Default database: 'app'. Query: 'INSERT INTO users(id,...) VALUES(...)'

Що це означає: Репліка застосувала щось не в порядку або відійшла вгору. Часто це викликано записами на репліку або фейловером, що підняв репліку, яка не мала частини транзакцій.

Рішення: Зупиніться. Не ігноруйте помилки. Визначте масштаб розбіжності: порівняйте GTID‑сети/позиції, виконайте перевірки консистентності і розгляньте відтворення репліки з відомо‑доброї снапшоту.

Завдання 13: Переконайтеся, що ніхто не пише в репліки (таке трапляється)

cr0x@server:~$ mysql -e "SHOW VARIABLES LIKE 'read_only'; SHOW VARIABLES LIKE 'super_read_only';"
+---------------+-------+
| Variable_name | Value |
+---------------+-------+
| read_only     | OFF   |
+---------------+-------+
+-----------------+-------+
| Variable_name   | Value |
+-----------------+-------+
| super_read_only | OFF   |
+-----------------+-------+

Що це означає: Репліка записувана. Це прийнятно лише якщо ви свідомо цього хочете (рідко) і розумієте наслідки.

Рішення: Увімкніть політично read_only і super_read_only для реплік. Якщо додатку потрібні записи — він потребує іншої архітектури, а не таємної виняткової настройки.

Завдання 14: Перевірте фільтри реплікації, що тихо відкидають дані

cr0x@server:~$ mysql -e "SHOW VARIABLES LIKE 'replicate%';" | egrep -v "replicate_(same_server_id|rewrite_db)"
replicate_do_db	app
replicate_ignore_db	mysql
replicate_wild_ignore_table	app.tmp_%

Що це означає: У вас налаштовано фільтрування реплікації. Це може бути валідним, але небезпечним при крос‑DB запитах і DDL.

Рішення: Аудитуйте кожен фільтр щодо реальних шаблонів навантаження. Якщо не можете довести, що це безпечно, приберіть фільтр і ізолюйте дані іншим способом (окремі інстанси, окремі кластери).

Швидкий план діагностики

Коли реплікація «повільна» або «зламана», ваше завдання — не дивитися на один метрик. Ваше завдання — швидко знайти обмежуючий ресурс і режим відмови, а потім вибрати найменш ризикове втручання.

Перше: репліка зупинилась чи бреше?

  • Перевірте SHOW SLAVE STATUS\G (або еквівалент) на предмет IO/SQL запущених тредів і помилок.
  • Якщо обидва треди працюють, не припускайте коректності. Підтверджуйте затримку через heartbeat і вибіркові перевірки даних.

Друге: в чому вузьке місце — мережа, диск чи блокування?

  • Мережа/IO‑тред: IO‑тред не працює, «підключається» або «перепідключається».
  • Диск/commit: SQL‑тред чекає на commit, високий iostat await, насичення %util.
  • Блокування/DDL: SQL‑тред застряг на метаданих; довготривалі DDL блокують аплай.

Третє: це mismatch формату/сумісності?

  • Перевірте формат binlog і змінні контрольних сум на обох кінцях.
  • Перевірте версійний розрив, відмінності плагінів і сумісність режиму GTID.

Четверте: вирішіть рівень втручання

  • Низький ризик: обмежити записи, додати місце на диску, виправити мережу, покращити I/O.
  • Середній ризик: підлаштувати паралельні воркери або застосувати налаштування з профілюванням.
  • Високий ризик: пропускати помилки, скидати стан репліки, відтворювати репліки, піднімати інший вузол. Високий ризик потребує письмового плану і відкату.

Типові помилки: симптом → причина → виправлення

1) «Seconds_Behind_Master = 0, але дані неправильні»

Симптом: Читання з реплік показує відсутні рядки або хибні агрегати; статус реплікації виглядає «добре».

Причина: Statement‑based дрейф, небезпечні функції, або фільтри, що відкидають події; іноді записи потрапили на репліки.

Виправлення: Перейдіть на row‑based binlog де можливо; приберіть ризикові фільтри; ввімкніть super_read_only; запустіть перевірки консистентності і відтворіть відхилену репліку.

2) «Реплікація зламалась після незначного оновлення»

Симптом: IO‑тред зупиняється з помилками парсингу подій; або SQL‑тред помилково обробляє невідомі типи подій.

Причина: Версійний розрив, що генерує binlog‑фічі, які репліка не може парсити; несумісність контрольних сум; несумісність режиму GTID між флейворами.

Виправлення: Узгодьте версії в підтримуваних межах; стандартизуйте binlog_checksum; перевіряйте сумісність GTID у лабораторії і на канарній репліці перед виходом.

3) «Затримка росте під час піків записів і не відновлюється»

Симптом: Relay log надуваються; SQL‑тред показує «Waiting for handler commit»; I/O гарячий.

Причина: Диск репліки — вузьке місце (fsync‑тиск, насичене сховище), не CPU. RBR збільшує ампліфікацію записів.

Виправлення: Перемістіть репліки на швидше сховище; налаштуйте InnoDB log; переконайтеся, що buffer pool налаштований; розгляньте тимчасове відкладення важких аналітичних запитів на репліках.

4) «Ми зробили фейловер з GTID і все одно втратили транзакції»

Симптом: Користувачі повідомляють про відсутні недавні записи; первинка померла; нову первинку підняли чисто.

Причина: Вікно асинхронної реплікації, напівсинхронне підтвердження лише отримання, або піднята репліка не була повністю наздоганою/застосованою.

Виправлення: Заблокуйте підвищення до підтвердженого наздоганяння; якщо використовуєте напівсинхронність, намагайтесь піднімати підтверджену репліку; посиліть налаштування стійкості, де потрібно.

5) «Паралельна реплікація все ускладнила»

Симптом: Збільшення воркерів збільшує затримку і CPU; пропускна здатність реплікації падає.

Причина: Контенція, «гарячі» рядки, серіалізація commit, чхання буфер пулу, або DDL, що блокує аплай.

Виправлення: Зменшіть кількість воркерів; профілюйте очікування; ставтесь до DDL як до запланованої події; шардуйте «гарячі» ділянки записів якщо потрібно; валідируйте налаштування під реальним навантаженням.

6) «Репліка падає і повертається зламана»

Симптом: Після перезавантаження репліка не може відновитись; relay log неконсистентні; потрібне ручне переміщення координат.

Причина: Метадані не стійкі до краху; relay_log_recovery вимкнено; проблеми з файловою системою/диском.

Виправлення: Увімкніть crash‑safe репозиторії (TABLE) і relay log recovery; перевірте здоров’я файлової системи; відтворіть репліку, якщо стан підозрілий.

Три корпоративні міні‑історії з реплікаційних рубежів

Міні‑історія 1: Інцидент через хибне припущення

Середній SaaS запуск мав змішане середовище: MariaDB для легасі‑продукту, Percona Server для новіших сервісів.
Нова команда успадкувала топологію крос‑дата‑центрної реплікації і стандартизувала рукопис фейловера навколо «GTID auto‑positioning».
Вони припустили, що GTID — це GTID. Той самий акронім, та сама безпека, такий самий результат.

Під час збою первинки вони підняли репліку за кроками, що бездоганно працювали у Percona.
Реплікація відновилась, додаток ожив, панелі стали зеленими. Усі зітхнули.
Потім почалися ескалації у службу підтримки: останні зміни підписок зникли, але тільки для деяких орендарів.

Постмортем був суворо повчальним. Стан GTID MariaDB інтерпретувався інструментом фейловера інакше, ніж вони думали.
Інструмент обрав кандидат‑репліку, яка виглядала наздоганою за одним метриком, але не була «найбільш просунутою» вузлом у семантиці домену GTID MariaDB.

Вони могли б виявити це перед боєм: перевіривши виконані набори транзакцій за правильними серверними змінними
і протестувавши крос‑флейворний фейловер у лабораторії з реальними binlog. Натомість вони навчилися в продакшні, що є найдорожчою аудиторією.

Виправлення не було героїчне. Вони розділили операційні рукописи за флейворами, ввели моніторинг із урахуванням флейвора і припинили вдавати,
що один універсальний скрипт автоматизації може безпечно керувати обома без явної логіки сумісності.

Міні‑історія 2: Оптимізація, що обернулась проти

Компанія електронної комерції мала типовий біль: репліки відставали під час промоцій.
Хтось запропонував просте рішення: послабити стійкість, щоб пришвидшити коміти і дати реплікам можливість наздогнати.
Знизили sync_binlog і змінили налаштування скидання логів також на репліках, бо «репліки не потребують такої стійкості».

Затримка покращилась деякий час. Команда святкувала тихе задоволення від зменшення мілісекунд на графіку.
Потім хост репліки перезавантажився під час оновлення ядра, і репліка повернулась з relay log, яким не можна довіряти.
Відновлення вимагало ручного втручання, а потім відтворення.

Під час вікна відтворення інші репліки взяли на себе більше читачів і більше навантаження реплікації.
Затримка повернулась, вже з меншими запобіжниками. Вони оптимізували для стійкого стану, збільшивши площу ураження при рутинних подіях.

Урок не був «ніколи не налаштовуйте». Це був «налаштовуйте з моделлю відмов». Якщо ви знижуєте стійкість, потрібно змоделювати наслідки при краху,
відключенні живлення і фейловері. Якщо ваша модель — «ймовірно, все гаразд», вітаю: ви прийняли народну інженерію.

Вони повернули ризикові налаштування, перемістили репліки на швидші диски і припинили використовувати налаштування стійкості як пластир продуктивності.
Сховище було вузьким місцем увесь час — як це часто буває.

Міні‑історія 3: Нудна, але правильна практика, що врятувала день

Платформа платежів працювала на Percona Server із суворою операційною дисципліною.
У них була щотижнева ритуал: перевіряти наздоганяння реплік, запускати перевірку контрольних сум частини таблиць,
репетиція контрольованого фейловера у staging із конфігурацією, що відтворює продакшн, і запис точних команд.
Ніхто цим не хвалився. Це не було «інновацією». Це була хатня робота.

Одного дня первинка почала давати переривчасті fsync‑завали. Затримка реплікації почала рости.
On‑call виконав план швидкої діагностики і підтвердив, що причина — латентність сховища, а не блокування SQL.
Вони звузили швидкість пакетного записувача, відтіснили трафік і підготувалися до фейловера.

Рятувальним фактором був gate для підвищення: вони піднімали лише ту репліку, що була підтверджено наздоганою через heartbeat і стан транзакцій,
і мали попередньо затверджений чекліст, щоб переконатися, що read‑only прапори і налаштування binlog правильні на новій первинці.

Фейловер був без пафосу. Він також був чистим. Ніяких пропущених транзакцій, ніякого дрейфу, ніякого «чому ця таблиця інша»‑пошуку.
Їхній найбільший стрес був очікування TTL DNS, що є правильним видом стресу.

Надійність — це переважно купа нудних звичок. Нудне недооцінене.

Цитата, варта стіни

Парафразована ідея (приписують Річарду Куку): «Успіх приходить від адаптації до сюрпризів; поразка — від тієї самої системи, що працює під напругою.»

Чеклісти / покроковий план

Чекліст A: Проєктування реплікації, щоб крайні випадки боліли менше

  1. Виберіть стратегію флейвора: лише MariaDB‑GTID, лише MySQL/Percona‑GTID або без GTID з явними позиціями. Уникайте «ми якось розберемося потім».
  2. Стандартизувати формат binlog (перевага ROW) і контрольні суми binlog по всьому флоту.
  3. Визначте свою позицію стійкості й задокументуйте RPO. Узгодьте sync_binlog і innodb_flush_log_at_trx_commit з цим вибором.
  4. Увімкніть crash‑safe метадані реплікації (master_info_repository=TABLE, relay_log_info_repository=TABLE, relay_log_recovery=ON) де підтримується і протестовано.
  5. Забезпечте read‑only для реплік (read_only і super_read_only).
  6. Виберіть метод вимірювання затримки, що відображає реальність (heartbeat‑базований).
  7. Визначте спосіб rollout DDL (заплановані вікна, інструменти онлайн‑змін схеми або модель міграцій на рівні додатку).

Чекліст B: Процедура підвищення / фейловера (версія безпечна для людей)

  1. Заморозьте записи, якщо можете (режим обслуговування додатку або обмеження записувача). Якщо не можете — принаймні знайте очікуване вікно втрат.
  2. Виберіть кандидата на підвищення на основі підтвердженого наздоганяння: затримка heartbeat близько нуля, треди реплікації здорові, немає SQL‑помилок.
  3. Перевірте стан транзакцій, використовуючи змінні GTID/позицій, коректні для вашого флейвора. Не «перекладайте в голові».
  4. Підтвердіть, що кандидат не записуваний перед підвищенням, якщо це не обумовлено. Потім свідомо переключіть на записуваний режим.
  5. Підвищення: чисто зупиніть реплікацію, скиньте конфіг реплікації за потреби, переконайтеся, що binlog увімкнено на новій первинці.
  6. Перенаправте інші репліки на нову первинку, використовуючи правильний auto‑position метод для вашого флейвора.
  7. Перевірте коректність вибірково і невеликим пробним тестом консистентності. Потім розморожуйте записи.

Чекліст C: Коли треба відтворити репліку (а це станеться)

  1. Зупиніть реплікацію і зафіксуйте поточний статус як запис у хронологію інциденту.
  2. Виберіть чисте джерело снапшоту (краще репліка, підтверджено коректна, не «найменше зламана»).
  3. Відновіть дані, потім обережно встановіть координати реплікації/стан GTID.
  4. Запустіть реплікацію і стежте за ранніми SQL‑помилками (дублікати, відсутні таблиці, проблеми з контрольними сумами).
  5. Запустіть цілеспрямовану перевірку консистентності по критичних таблицях перед поверненням у сервіс.

Жарт №2

Фільтри реплікації — як офісна політика: здаються корисними, поки не зрозумієш, що вони тихо відкидають важливу інформацію.

Поширені питання

1) Чи може MariaDB реплікувати з Percona Server (або навпаки) безпечно?

Іноді, у конкретних поєднаннях версій і конфігурацій, але «безпечність» вимагає тестування вашого точного формату binlog,
режиму контрольних сум і стратегії GTID. Крос‑флейворний GTID — місце, де команди кусаються. Якщо мусите змішувати, робіть це з лабораторією, що програє реальні binlog‑файли.

2) Чи варто використовувати GTID скрізь?

Так, якщо ваш інструментарій і процедури команди GTID‑нативні для обраного флейвора. Ні, якщо ви змішуєте флейвори без плану сумісності.
GTID покращує ергономіку фейловера, але не усуває вікна втрат даних або погані рішення підвищення.

3) Чи є напівсинхронна реплікація «без втрати даних»?

Ні. Вона зменшує вікно, гарантуючи, що принаймні одна репліка отримала подію перед ACK клієнту, але отримання ≠ застосування.
Ви все ще можете втратити транзакції залежно від часу краху і вибору фейловера.

4) Чому затримка реплікації стрибає під час DDL навіть з паралельною реплікацією?

DDL часто серіалізує виконання і може захоплювати метадані‑блоки, що блокує аплай. Паралельні воркери не проходять блокуючу подію.
Розглядайте великі зміни схеми як заплановані події і тестуйте їх під навантаженням, схожим на продакшн.

5) Який найнадійніший метрик затримки для рішень фейловера?

Heartbeat‑базовані вимірювання (наприклад, метка часу, записана на первинці і прочитана на репліках) зазвичай правдивіші, ніж
Seconds_Behind_Master, особливо при паралельному аплаї або коли SQL‑тред періодично блокується.

6) Якщо реплікація зламана, чи слід пропускати проблемну транзакцію?

Лише у крайньому випадку, і тільки коли ви повністю розумієте, що саме пропускаєте і як будете відновлювати консистентність.
Пропуск — це операційний борговий інструмент з складними відсотками.

7) Чому репліки відходять, навіть коли реплікація каже, що вона працює?

Типові причини: statement‑based реплікація з недетермінованістю, записи, що потрапили на репліки, фільтри реплікації та
поведінка додатку, що залежить від сесійних налаштувань, які не реплікуються як очікувалося. Розбіжність — частіше політична помилка, а не таємниця.

8) Як найшвидше визначити, чи вузьке місце — сховище?

Якщо стани SQL‑треда показують очікування коміту і iostat показує високий await/%util — це сховище.
Виправте сховище або зменшіть тиск записів. Не «оптимізуйте» параметри реплікації в стіну диска.

9) Чи змінюють специфічні для Percona функції поведінку реплікації?

Percona Server зазвичай близький до семантики Oracle MySQL, але додаткова інструментація і регулювання можуть змінити поведінку продуктивності.
Ставте його як флейвор першого класу: тримайте конфігурації консистентними і тестуйте оновлення, особливо навколо паралельної реплікації і стійкості.

10) Який сьогодні найбезпечніший вибір формату binlog?

Row‑based реплікація — типовий вибір за імовірністю коректності. Вартість — більший обсяг binlog і більше I/O на репліках.
Якщо обираєте statement‑based, вам потрібен суворий контроль SQL‑патернів і висока толерантність до «сюрпризного дрейфу».

Наступні кроки, які ви можете зробити цього тижня

Якщо хочете менше інцидентів реплікації, не починайте з суперечки про бренди. Почніть із усунення неоднозначності.

  1. Перерахуйте флейвори і версії по вашій топології. Запишіть це. Припиніть вважати «все — MySQL».
  2. Стандартизуйте формат binlog і контрольні суми і перевірте це командами на кожному вузлі.
  3. Визначте і задокументуйте RPO, потім узгодьте налаштування стійкості з цим. Якщо бізнес не може вирішити, оберіть консервативні налаштування і дозвольте їм сплатити рахунок за латентність.
  4. Впровадьте heartbeat‑заміри затримки і використовуйте їх в алертах і як умову фейловера.
  5. Проведіть контрольну репетицію фейловера у staging з продакшн‑подібними налаштуваннями. Засічіть час. Виправте кроки, що потребують «племінних знань».
  6. Оберіть одну «нудну практику коректності» (примусове read‑only, crash‑safe метадані реплікації, щотижневі перевірки консистентності) і зробіть її політикою.

Крайні випадки реплікації байдуже, який дистрибутив ви встановили. Їм важливі ваші припущення, що ви протестували, і що ви готові тримати консистентним, коли ніхто не дивиться.

← Попередня
Ubuntu 24.04: Docker + UFW = Несподівано відкриті порти — закрийте діру, не зламавши контейнери
Наступна →
ZFS logbias: Затримка проти пропускної здатності — оберіть те, що дійсно потрібно

Залишити коментар