Більшість відмов баз даних у виробництві починаються не з драматичної помилки. Вони починаються з «розумного» налаштування, нового характеру навантаження й тихого припущення, що сервер поводитиметься так само, як і минулого кварталу.
Якщо ви довго експлуатуєте MySQL у продакшені, ви болісно вчитеся, що «воно працює» — не те саме, що «воно безпечно відмовляється». Тут Percona Server (форк, сумісний з MySQL) історично заробляв свою ціну: практичні налаштування за замовчуванням, додаткова інструментація й ухил на виживання, коли у вашого застосунку кепський день.
Рішення: коли Percona варта витрат (а коли ні)
Є дві розумні причини змінювати дистрибутив бази даних у продакшені: ви хочете менше простоїв або швидше діагностувати проблеми під час інцидентів. Percona Server зазвичай допомагає в обох випадках, переважно через те, що він історично містив операційні функції й інструментацію, які upstream MySQL або ще не включав, або приховував за enterprise-пропозиціями, або вимагали більше зусиль, щоб стати дієвими.
Обирайте upstream MySQL коли
- Вам потрібна найконсервативніша сумісність. Upstream MySQL (Oracle) визначає базову лінію. Всі спочатку тестують проти нього.
- Ви вже стандартизувалися на циклі випуску й інструментах Oracle. Якщо у вашій організації MySQL — продукт постачальника з формальним контрактом підтримки й жорстким фіксуванням версій, залишайте все просто.
- Ваша операційна зрілість достатньо висока, і «безпечніші налаштування» не мають значення. Якщо у вас уже базове управління конфігурацією відображає реальність, плюс алерти на тиск InnoDB, плюс регулярні тести відновлення після аварій — тоді дистрибутив менш критичний, ніж дисципліна.
Обирайте Percona Server коли
- Ви хочете кращу спостережуваність з коробки. На практиці різниця часто в тому, що «ми можемо це бачити» проти «ми думаємо, що це так».
- Вам потрібні операційні функції, що зменшують «підступи». Історично: сильніша інструментація, регулювання продуктивності й сумісність інструментів для даних у стані спокою (особливо в екосистемі Percona).
- Ви керуєте флотом серверів. Коли ви оперуєте десятками чи сотнями інстансів MySQL, вартість поганого значення за замовчуванням множиться. Ухил Percona до поведінки, дружньої до операцій, може окупитися однією уникненою аварією.
Чого не слід робити: переходити дистрибутиви як «хак для продуктивності». Якщо ви в такому настрої, ви отримаєте «перемогу по бенчмарку», а потім втратите її через крайовий випадок реплікації, сюрприз у бекапах або рестарт, що займає більше часу, ніж усе ваше SLA-бюджет.
Правило великого пальця: якщо ваша найбільша проблема — відмови й повільний аналіз причин, Percona Server часто є прагматичним вибором. Якщо головна проблема — «юридична та закупівельна», використовуйте upstream MySQL і інвестуйте в інструментацію та руктбуки.
Історичний контекст і факти, що мають значення
Деякі факти — це тривія. Це не ті. Вони впливають на те, як команди доставляють ризики.
- MySQL AB був придбаний Sun у 2008 році, а Sun — Oracle у 2010 році. Екосистема форків (Percona, MariaDB) прискорилася, бо людям не подобається невизначеність навколо критичної інфраструктури.
- Percona починалася як компанія з продуктивності та підтримки перед тим, як почати постачати свої збірки сервера. Такий початок пояснює вибір функцій з ухилом «для операторів».
- InnoDB став стандартним рушієм зберігання в MySQL роками тому, замінивши роль MyISAM. Цей зсув зробив відновлення після аварій і налаштування стійкості центром операційної правильності.
- Performance Schema починався як «цікаво, але важко», а потім став основною поверхнею для спостережуваності. Багато команд досі тримають його напіввиключеним через старі легенди.
- Percona популяризувала операційні інструменти навколо MySQL, особливо гарячі бекапи. Це сформувало очікування: бекапи повинні бути швидкими, перевірюваними і не вимагати простою.
- Реплікація в MySQL еволюціонувала від statement-based до row-based і змішаних режимів. Це було не академічно; це відповідь на реальний дрейф даних і недетермінованість.
- Поведінка редо-логу InnoDB і флашінг налаштовувалися в різних версіях. «За замовчуванням» стійкість і продуктивність — рухомі цілі; старі поради тепер можуть бути неправильними.
- MySQL 8 змінив операційну відчутність: словник даних, покращений EXPLAIN, краща поведінка за замовчуванням для наборів символів. Це також змінило ризики оновлень і інструментальні припущення.
- Percona Server історично публікував додаткові лічильники статусу та регулятори. Коли ви діагностуєте затримки, лічильники краще за інтуїцію.
Безпечніші налаштування: що насправді означає «безпечніше»
«Безпечніші налаштування» — це не моральне твердження. Це про те, як системи поводяться під навантаженням і під час відмов: затримки диска, тиск контрольних точок, довгі транзакції, реплікаційне відставання або класичне «ми просто подвоїли трафік». База даних, яка відмовляється повільно й гучно, безпечніша за ту, що падає швидко й тихо.
Осьова безпеки 1: передбачувана стійкість
Найпоширеніша «підступність» у MySQL у продакшені — це компроміси стійкості, сховані за налаштуваннями продуктивності. Дивна кількість команд працювала з innodb_flush_log_at_trx_commit=2 або sync_binlog=0 заради «швидкості», а потім виявляла, що їхній RPO при краху — «що відчуває ядро».
Percona Server не чарівно вирішує погані рішення щодо стійкості, але збірки, орієнтовані на операторів, мають тенденцію яскравіше документувати й виводити на поверхню ці компроміси, а суміжна екосистема (наприклад, Percona Monitoring) ускладнює вдавання, що ви в безпеці, коли це не так.
Осьова безпеки 2: менше налаштувань, щоб досягти адекватної продуктивності
Більшість порад з налаштування MySQL в інтернеті — це викопалини. Їх також пишуть люди, які не несуть ваш pager.
Безпечні за замовчуванням — ті, де пристойно обладнана машина з розумною конфігурацією не падає з обриву при зростанні конкурентності. Хороше за замовчуванням — «не ганебно під навантаженням». Чудове — «не викликає аварії, якщо ви забули один параметр».
Осьова безпеки 3: видимість справжнього вузького місця
Якщо ви не можете приписати затримку диску, блокування, промахи буферного пулу, конкуренцію редо або застосування реплікації, ви налаштуєте не те. Найбільшою практичною перевагою Percona Server часто було те, що він давав більше важелів для спостереження й вимірювання, а не порушував фізику.
Перший жарт (ви отримуєте рівно два): Конфіг MySQL без коментарів — як парашут, упакований «майбутнім вами». Він працює до того моменту, поки не знадобиться.
Спостережуваність: різниця між здогадом і знанням
Коли затримка зростає, керівники питають «база даних впала?». Інженери питають «це CPU, IO, блокування чи реплікація?». Ваш успіх визначається тим, як швидко ви можете відповісти на друге питання, а не тим, наскільки впевнено відповісти на перше.
Що треба спостерігати (в порядку важливості)
- Тиск конкурентності: кількість працюючих потоків, сплески з’єднань, пропуски кешу потоків та перервані з’єднання.
- Стан InnoDB: коефіцієнт потрапляння в буферний пул, відсоток модифікованих сторінок, вік контрольної точки/тиск редо, довжина списку історії.
- Блокування: очікування блокувань рядків, очікування метаданих, довгі транзакції, що утримують блокування.
- IO: затримка fsync, записи редо-логу, читання файлів даних, активність doublewrite.
- Реплікація: відставання застосування, простір relay log, черги воркерів.
Де команди MySQL помиляються
Вони дивляться на CPU, бачать, що він низький, і оголошують базу «в порядку». Потім дивляться на завантаження диска і бачать, що воно не зашкалило, і оголошують сховище «в порядку». Тим часом реальна проблема — варіація затримок fsync (p99), або одна транзакція, що фіксує очищення, або метаданте блокування від онлайн-зміни схеми. Жодна з них не проявиться чисто в «CPU% і disk%».
Додана вартість Percona часто була: більше дієвих лічильників і культура відкриття внутрішніх станів. Upstream MySQL поступово зменшив цю прогалину, але різниця в операційній філософії все ще проявляється в тому, що ввімкнено за замовчуванням і наскільки «очевидні» дані.
Одна цитата (парафраз): ідея Werner Vogels полягає в тому, що слід «проектувати під відмови», очікуючи, що частини зламаються, а ваша система має продовжувати працювати.
Стійкість і безпека при збоях: чим ви жертвуєте заради швидкості
У продакшені «стійкість» — не чекбокс. Це угода між InnoDB, бінлогом, файловою системою, ядром, гіпервізором і іноді мережею зберігання, яка чемно вам бреше.
Основні регулятори, що визначають ваш RPO
innodb_flush_log_at_trx_commit: контролює, як охоче InnoDB виконує fsync редо при коміті.sync_binlog: контролює, як охоче бінлог fsync-иться.binlog_formatта налаштування GTID: впливають на коректність реплікації й поведінку при перемиканні.
Як виглядають «безпечніші налаштування»
Безпечні за замовчуванням віддають перевагу коректності після збою, аніж бенчмарку. Якщо ви працюєте з фінансовими чи інвентарними системами, не будьте хитрунами. Якщо ви обслуговуєте кешоподібне навантаження з припустимими втратами даних — задокументуйте це явно, виміряйте свій RPO і переконайтеся, що керівництво підписалося під цим.
Сумна правда: ви можете купити продуктивність слабшою стійкістю, але не можна купити цілісність постфактум. Бекапи допомагають, але вони не виправлять спліт-брейн, дрейф реплікації або розрив між «підтверджено клієнту» і «записано на диск».
Реплікація та перемикання: менше несподіванок
Реплікація — це місце, куди «працює в стагінгу» йде помирати. Навантаження інше, запити брудніші, і хтось неминуче виконає екстрений DDL у найгірший момент.
Операційні уподобання, що зменшують біль
- Використовуйте GTID там, де це доречно. Це робить інструменти перемикання менш крихкими і зменшує археологію «яка позиція бінлогу?».
- Віддавайте перевагу реплікації на рівні рядків (row-based) заради коректності. Реплікація на рівні інструкцій — музейний експонат: цікава, але не місце для бізнес-логіки.
- Тримайте відставання реплікації видимим і дієвим. Відставання — це не просто число; це симптом. Вимірюйте черги застосування, затримки воркерів і очікування блокувань на репліках.
Percona Server історично покращував досвід тут, роблячи статус реплікації більш діагностованим. Навіть якщо upstream MySQL звузив цю прогалину, екосистема Percona припускає, що ви дійсно подивитесь на внутрішні показники реплікації. Це здорове припущення.
Зберігання та реалії файлових систем (чого SRE вчаться о 3-й ночі)
MySQL — це рушій зберігання в костюмі SQL. Він дуже переймається поведінкою fsync, написанням, що посилює запис, і варіаціями затримок. Він також має довгу пам’ять: одна погана архітектурна рішення по зберіганню може переслідувати вас місяцями, бо «фікс» вимагає переміщення даних або простою.
Варіація затримок перемагає пропускну здатність (в найгірший спосіб)
Більшість відмов, які списують на «диск повільний», насправді — «диск час від часу повільний». Середнє виглядає нормально, p95 нормальний, p99 — фільм жахів. InnoDB чутливий до зупинок у флашингу журналу й контрольних точок. Коли така зупинка трапляється, потоки наростають у стек, час відповіді вибухає, і ваш on-call дивиться на дашборди, що виглядають нормально — поки не стануть.
Файлові системи й опції
Чи ви використовуєте ext4 чи xfs, локальний NVMe чи мережеве сховище, невід’ємне — fsync має працювати. Якщо ви використовуєте віртуалізацію чи мережеве сховище, перевірте, що флаші справжні флаші. Деякі шари охоче підтверджують записи, які ще не збережені фізично. Це не «швидко». Це «майбутній інцидент».
Другий жарт: Єдина річ більш оптимістична, ніж прогноз продажів, — це контролер сховища, що каже, що його кеш «фактично стійкий».
Три короткі історії з корпоративного життя
1) Інцидент, спричинений хибним припущенням: «Коміт означає, що це на диску»
Середній SaaS працював на MySQL для білінгу та рахунків. Їхня основна база була на віртуалізованому блочному пристрої з бекендом сховища, що обслуговував постачальник. Він бенчмаркувався чудово. Затримки були низькі, пропускна здатність висока, всі йшли додому вчасно.
Під час інциденту в датацентрі VM перезавантажилася. MySQL піднявся чисто, але застосунок почав повідомляти про «відсутні рахунки» за вузький часовий проміжок. Спочатку незначно. Потім звернень у підтримку стало багато, і фінанси помітили невідповідності між callback-ами платіжного провайдера та внутрішніми записами регістра.
Команда налаштувала innodb_flush_log_at_trx_commit=2, щоб знизити тиск fsync, і лишила sync_binlog=0, бо «fsync бінлогу дорогий». Вони також припускали, що шар зберігання має батарейний кеш і безпечно зберігає записи. Платформа постачальника дійсно мала кеш, але гарантії стійкості під час відмов були не тими, яких команда очікувала. Частина підтверджених записів так і не дійшла.
Виправлення було нудним і болючим: повернути налаштування стійкості до безпечних значень, перевірити семантику флашів сховища і прийняти витрати на продуктивність. Також додали розділ у рукописі з назвою «Який у нас фактичний RPO?», бо ніхто не міг відповісти чесно до інциденту.
2) Оптимізація, що відкинула назад: «Більший buffer pool вирішує все»
Внутрішня аналітична платформа мала інстанс MySQL для змішаних OLTP-записів і важких читань. On-call втомився від періодичних уповільнень під час місячних звітів. Хтось запропонував класичне рішення: збільшити innodb_buffer_pool_size, поки дані «не вмістяться в пам’ять».
Вони розкрутили buffer pool на велику частку RAM, лишивши лише тонку подушку для кешу OS, фонових потоків, сплесків з’єднань і агента моніторингу. Інстанс став швидшим — аж поки перший насичений день після зміни не настав.
Під вищою конкурентністю ядро почало трохи свапити. Не багато, але достатньо. Латентність MySQL стала нелінійною. Потоки стояли, реплікаційне відставання зросло, і резерв теж зазнав труднощів, бо мав ту саму схему налаштування. Команда «оптимізувала» пам’ять і випадково створила аварію через свап.
Відновлення було простим: зменшити buffer pool, обмежити з’єднання, вимкнути або жорстко контролювати свап, і встановити явні цілі запасу пам’яті. Більший урок: зміна, що покращує середню латентність, може знищити хвостову латентність і доступність.
3) Нудна, але правильна практика, що врятувала ситуацію: регулярні вправи з відновлення
Ритейл-компанія мала мульти-орендну флотилію MySQL. Вони не були вишукані. Але у них був календарний запрошення: раз за спринт хтось відновлював продакшен-бекап в ізольоване середовище і проганяв перевірку консистентності плюс кілька валідяцій на рівні застосунку.
Одного вівторка розробник виконав міграцію, яка випадково видалила індекс і запустила бекафіл, що оновлював рядки в патологічному порядку. Прайм вижив, але реплікаційне відставання вибухнуло. Репліка відстала на години, і звичний план «підняти репліку» перестав заспокоювати.
Вони вирішили відновити з останнього бекапу на новий інстанс і потім застосувати бінлоги до безпечної точки. Це спрацювало переважно тому, що вони це практикували. Вони також знали, скільки часу займає відновлення на їхньому обладнанні, які типові точки відмови і які перевірки консистентності реально ловлять проблеми.
Вікно простою все одно було болючим, але воно було обмеженим. Команда не винаходила процес відновлення в стресі. Вони виконали той, який репетирували — а це найближче до магії в операціях.
Практичні завдання: команди, виводи й рішення
Нижче реальні завдання, які ви можете виконати сьогодні. Кожне містить: команду, приклад виводу, що це означає, і рішення, яке з цього випливає. Вони незалежні від дистрибутива, якщо не вказано інше. Сенс не в запам’ятовуванні команд; сенс — виробити звичку вимірювати перед налаштуванням.
Завдання 1: підтвердити, що саме ви запускаєте (версія й дистрибутив)
cr0x@server:~$ mysql --version
mysql Ver 8.0.36-28 for Linux on x86_64 (Percona Server (GPL), Release 28, Revision 1234567)
Що це означає: Ви не можете порівнювати поведінку між серверами, якщо не знаєте точну збірку. Мінорні релізи змінюють значення за замовчуванням і внутрішні механізми.
Рішення: Фіксуйте версії навмисно. Якщо ви дебагуєте, відтворюйте на тій самій мінорній версії перед тим, як звинувачувати навантаження.
Завдання 2: переглянути ефективні змінні виконання (не те, що ви думаєте у my.cnf)
cr0x@server:~$ mysql -e "SHOW VARIABLES LIKE 'innodb_flush_log_at_trx_commit'; SHOW VARIABLES LIKE 'sync_binlog';"
+--------------------------------+-------+
| Variable_name | Value |
+--------------------------------+-------+
| innodb_flush_log_at_trx_commit | 1 |
+--------------------------------+-------+
+---------------+-------+
| Variable_name | Value |
+---------------+-------+
| sync_binlog | 1 |
+---------------+-------+
Що це означає: Ви використовуєте сильні налаштування стійкості.
Рішення: Тримайте їх, якщо лише у вас немає підписаного винятку RPO і ви не протестували поведінку відновлення на вашому сховищі.
Завдання 3: перевірити, чи увімкнено Performance Schema
cr0x@server:~$ mysql -e "SHOW VARIABLES LIKE 'performance_schema';"
+--------------------+-------+
| Variable_name | Value |
+--------------------+-------+
| performance_schema | ON |
+--------------------+-------+
Що це означає: У вас є доступ до сучасних таблиць спостережуваності для подій очікування, запитів і стадій.
Рішення: Якщо воно вимкнене, припиніть літати в сліпу. Увімкніть його в наступному вікні обслуговування, якщо нема виміряних причин не робити цього.
Завдання 4: визначити топ-запитів за сумарною латентністю (де насправді пішов час)
cr0x@server:~$ mysql -e "SELECT DIGEST_TEXT, COUNT_STAR, ROUND(SUM_TIMER_WAIT/1000000000000,2) AS total_s FROM performance_schema.events_statements_summary_by_digest ORDER BY SUM_TIMER_WAIT DESC LIMIT 3\G"
*************************** 1. row ***************************
DIGEST_TEXT: SELECT * FROM orders WHERE user_id = ? ORDER BY created_at DESC LIMIT ?
COUNT_STAR: 982134
total_s: 18643.51
*************************** 2. row ***************************
DIGEST_TEXT: UPDATE inventory SET qty = qty - ? WHERE sku = ?
COUNT_STAR: 371223
total_s: 9221.09
*************************** 3. row ***************************
DIGEST_TEXT: SELECT COUNT(*) FROM events WHERE tenant_id = ? AND created_at > ?
COUNT_STAR: 8122
total_s: 3112.44
Що це означає: Перші два запити домінують у загальному часі. Третій дорого коштує на виклик (мало викликів, багато часу).
Рішення: Робота над індексами й формою запитів перевищує налаштування сервера. Спочатку виправте третій запит, якщо він драйвить хвостову латентність.
Завдання 5: побачити стан InnoDB і «справжню історію» за затримками
cr0x@server:~$ mysql -e "SHOW ENGINE INNODB STATUS\G"
...
Buffer pool size 262144
Free buffers 1024
Database pages 258000
Modified db pages 42000
...
Log sequence number 987654321098
Log flushed up to 987654320900
Last checkpoint at 987654300000
...
History list length 183421
...
Що це означає: Багато брудних сторінок, контрольна точка позаду, і велика довжина списку історії. Можливо, відстає purge (часто через довгі транзакції).
Рішення: Шукайте довгі транзакції й усувайте їх. Якщо це хронічно, перегляньте розмір редо-логу й шаблон записів.
Завдання 6: знайти довгі транзакції, що тримають purge
cr0x@server:~$ mysql -e "SELECT trx_id, trx_started, trx_state, trx_rows_locked, trx_rows_modified, trx_query FROM information_schema.innodb_trx ORDER BY trx_started ASC LIMIT 3\G"
*************************** 1. row ***************************
trx_id: 123456789
trx_started: 2025-12-30 02:11:09
trx_state: RUNNING
trx_rows_locked: 0
trx_rows_modified: 148220
trx_query: UPDATE events SET processed=1 WHERE tenant_id=42 AND processed=0
...
Що це означає: Довга оновлювальна транзакція модифікує багато рядків і, ймовірно, роздуває undo/історію.
Рішення: Розбивайте батчі на менші коміти; додайте обмеження швидкості; розгляньте індексування, щоб уникнути широких сканів, які довго утримують блокування.
Завдання 7: впіймати метадані-блокування (тиха відмова)
cr0x@server:~$ mysql -e "SELECT * FROM performance_schema.metadata_locks WHERE LOCK_STATUS='PENDING' LIMIT 5\G"
*************************** 1. row ***************************
OBJECT_TYPE: TABLE
OBJECT_SCHEMA: app
OBJECT_NAME: users
LOCK_TYPE: EXCLUSIVE
LOCK_STATUS: PENDING
OWNER_THREAD_ID: 812
OWNER_EVENT_ID: 45678
Що це означає: Хтось хоче ексклюзивне блокування таблиці і заблокований. Це може заморозити трафік у дивні способи.
Рішення: Ідентифікуйте блокуючу сесію (join до threads) і виріште, вбити її чи чекати. Плануйте DDL правильно.
Завдання 8: перевірити відставання реплікації і чи воно IO- чи SQL-зв’язане
cr0x@server:~$ mysql -e "SHOW REPLICA STATUS\G"
...
Replica_IO_Running: Yes
Replica_SQL_Running: Yes
Seconds_Behind_Source: 187
Relay_Log_Space: 2147483648
...
Last_SQL_Error:
...
Що це означає: Реплікація працює, але застосування відстає. Relay log займає багато місця, що вказує на накопичення.
Рішення: Перевірте очікування блокувань на репліці, повільні запити в apply або недостатню конфігурацію паралельної реплікації. Не перемикайтеся на відсталу репліку.
Завдання 9: знайти піки з’єднань і насичення потоків
cr0x@server:~$ mysql -e "SHOW GLOBAL STATUS LIKE 'Threads_%';"
+-------------------+--------+
| Variable_name | Value |
+-------------------+--------+
| Threads_cached | 12 |
| Threads_connected | 1450 |
| Threads_created | 983221 |
| Threads_running | 198 |
+-------------------+--------+
Що це означає: Багато з’єднань, високий показник створення потоків з часом. Можливо, thread cache занадто малий або застосунок часто перестворює з’єднання.
Рішення: Спочатку виправте пулювання з’єднань. Потім налаштуйте thread_cache_size і застосуйте розумні max_connections з механізмом backpressure.
Завдання 10: перевірити, чи не досягаєте лімітів дескрипторів файлів (класика під навантаженням)
cr0x@server:~$ sudo systemctl show mysql -p LimitNOFILE
LimitNOFILE=65535
Що це означає: mysqld має визначений ліміт FD. При великій кількості з’єднань + таблиць низькі ліміти викликають «Too many open files».
Рішення: Підніміть ліміти за потреби, але також зменшіть кількість відкритих таблиць і уникайте абсурдних чисел з’єднань.
Завдання 11: перевірити затримку диска на рівні ОС (не «util%»)
cr0x@server:~$ iostat -x 1 3
avg-cpu: %user %nice %system %iowait %steal %idle
12.41 0.00 4.10 6.33 0.00 77.16
Device r/s w/s rkB/s wkB/s await svctm %util
nvme0n1 312.0 1240.0 9012.0 38200.0 18.45 0.62 96.12
Що це означає: await високий (18ms), тоді як використання близьке до максимуму. Це може пояснити fsync-затримки і латентність комітів.
Рішення: Якщо це постійно, вам потрібне швидше сховище, менше write amplification (перегляд схеми/індексів) або зниження конкурентності. Тюнінг не врятує насичений пристрій.
Завдання 12: перевірити, що MySQL дійсно флашить (і як часто)
cr0x@server:~$ mysql -e "SHOW GLOBAL STATUS LIKE 'Innodb_os_log_fsyncs'; SHOW GLOBAL STATUS LIKE 'Innodb_os_log_written';"
+---------------------+----------+
| Variable_name | Value |
+---------------------+----------+
| Innodb_os_log_fsyncs| 18273421 |
+---------------------+----------+
+-----------------------+-------------+
| Variable_name | Value |
+-----------------------+-------------+
| Innodb_os_log_written | 91234567890 |
+-----------------------+-------------+
Що це означає: Часті fsync відбуваються; для стійкості це нормально. Питання в тому, чи вони повільні.
Рішення: Корелюйте з піками латентності та затримками диска на рівні ОС. Якщо число fsync низьке, але застосунок «швидкий», можливо, ви випадково працюєте без стійкості.
Завдання 13: шукати тиск кеша таблиць (приховане навантаження CPU)
cr0x@server:~$ mysql -e "SHOW GLOBAL STATUS LIKE 'Open_tables'; SHOW GLOBAL STATUS LIKE 'Opened_tables'; SHOW VARIABLES LIKE 'table_open_cache';"
+---------------+-------+
| Variable_name | Value |
+---------------+-------+
| Open_tables | 4000 |
+---------------+-------+
+---------------+----------+
| Variable_name | Value |
+---------------+----------+
| Opened_tables | 12833422 |
+---------------+----------+
+------------------+-------+
| Variable_name | Value |
+------------------+-------+
| table_open_cache | 4096 |
+------------------+-------+
Що це означає: Opened_tables величезне; ви постійно відкриваєте таблиці, що додає накладні витрати.
Рішення: Збільшіть table_open_cache, якщо пам’ять дозволяє, і виправте навантаження, що створює надмірне тертя таблиць (наприклад занадто багато партицій або тимчасових таблиць).
Завдання 14: зробити разове знімок «що зараз виконується»
cr0x@server:~$ mysql -e "SHOW FULL PROCESSLIST;"
Id User Host db Command Time State Info
812 app 10.0.2.41:51122 app Query 12 Sending data SELECT * FROM orders WHERE user_id=...
901 app 10.0.2.17:42311 app Query 45 Waiting for table metadata lock ALTER TABLE users ADD COLUMN ...
1002 repl 10.0.3.9:60012 NULL Binlog Dump 81234 Master has sent all binlog to slave; waiting for more updates NULL
Що це означає: DDL блокує запити через метадані-блокування, і принаймні один запит проводить час у «Sending data» (зазвичай скан/великий результат або повільний клієнт).
Рішення: Перестаньте робити довільні DDL у робочий час. Використовуйте підходи онлайн-зміни схеми і перевіряйте поведінку блокувань. Виправте запит/індекс для скану.
План швидкої діагностики
Це порядок дій «дістатися до вузького місця за хвилини». Не імпровізуйте. Коли імпровізуєте, ви ганяєтесь за найгучнішим метриком, а не за правильним.
Спочатку: насичення, очікування чи єдиний блокувальник?
- Перевірте конкурентність:
Threads_running,Threads_connected, churn з’єднань. - Перевірте processlist на очевидні блокувальники: очікування метаданих, довгі запити, стани «Locked».
- Перевірте статус реплікації (якщо читання йдуть з реплік): відставання може виглядати як «база повільна», коли насправді «репліка відстала».
По-друге: це варіація IO чи конкуренція CPU?
- На рівні ОС:
iostat -xдля await і %util;vmstat 1для черги виконання й свапу. - На рівні MySQL: InnoDB status для контрольних точок, брудних сторінок, довжини списку історії; Performance Schema для подій очікування.
По-третє: це патологія блокувань/транзакцій?
- Довгі транзакції: запит до
information_schema.innodb_trx. - Очікування блокувань рядків: InnoDB status і Performance Schema waits.
- Метадані-блокування:
performance_schema.metadata_locksз очікуваними записами.
По-четверте: це регресія запитів?
- Топ-запити за digest-латентністю.
- EXPLAIN-плани для найгірших виконавців.
- Перевірте відсутні/зламані індекси або зміну параметрів, що спричинила інший план.
Операційна дисципліна: Завжди робіть знімок (processlist, статус реплікації, InnoDB status, iostat) перед «виправленням» чогось. Інакше ви знищите докази.
Поширені помилки: симптом → корінь → виправлення
1) Симптом: раптові глобальні сплески латентності, CPU низький
Корінь: fsync-зупинки (флаш редо-журналу) через варіацію затримок сховища або насичений пристрій.
Виправлення: Підтвердіть через iostat -x await і InnoDB контрольну точку/тиск редо. Зменшіть write amplification, покращіть сховище і не робіть «відключення стійкості» постійним рішенням.
2) Симптом: запити зависають під час деплою, потім раптово відновлюються
Корінь: конкуренція метаданих через DDL (ALTER TABLE), що чекає за довгою транзакцією.
Виправлення: Ідентифікуйте очікувані блокування в performance_schema.metadata_locks; убийте блокуючу сесію, якщо безпечно; плануйте DDL з онлайн-методами і таймаутами.
3) Симптом: відставання репліки зростає після додавання індексу
Корінь: DDL або backfill створює величезний обсяг записів; apply на репліці стає IO- або блокувально-зав’язаний.
Виправлення: Тротлінгуйте міграції, використовуйте онлайн-зміни схеми, налаштовуйте паралельну реплікацію тільки після вимірювань. Не піднімайте відсталу репліку.
4) Симптом: «Занадто багато з’єднань» і флапінг доступності
Корінь: шторм з’єднань у застосунку, відсутність пулування або зовнішній інцидент, що викликає повтори.
Виправлення: Впровадьте backpressure (знижте max_connections нижче за «нескінченність»), виправте пулювання і встановіть розумні таймаути. Високі ліміти з’єднань ховають баги застосунку, поки база не помре.
5) Симптом: поступове уповільнення протягом днів, потім періодичні зависання
Корінь: довгі транзакції перешкоджають purge; росте history list length; тиск на undo tablespace.
Виправлення: Розбивайте батчі на частини, уникайте інтерактивних сесій, що тримають транзакції відкритими, моніторте long trx і виправляйте шаблон застосунку.
6) Симптом: репліка «працює», але читання застарілі
Корінь: відставання репліки приховано маршрутизацією або моніторингом, що перевіряє лише «SQL thread running».
Виправлення: Ставте алерти на Seconds_Behind_Source плюс метрики черги застосування. Маршрутуйте читання з урахуванням відставання.
7) Симптом: після аварії дані неконсистентні між праймом і репліками
Корінь: нестійкі налаштування (flush/binlog) у поєднанні з крашем; або небезпечний формат/запити реплікації.
Виправлення: Використовуйте безпечні налаштування стійкості, якщо не відхилено явно; віддавайте перевагу row-based реплікації; тестуйте відновлення після краху через хаос-тестування.
Контрольні списки / покроковий план
Якщо ви оцінюєте Percona Server за «безпечніші налаштування»
- Інвентар версій і функцій, від яких ви залежите. Занотуйте плагіни аутентифікації, використання GTID, шифрування, інструменти бекапів і моніторинг.
- Підніміть canary-інстанс з імітацією продакшен-сховища й, якщо можна, відтворенням трафіку.
- Увімкніть Performance Schema і зберіть базові показники (digest summaries, wait events, InnoDB metrics).
- Проведіть тести збою, що імітують ваш найгірший день: kill -9 mysqld, перезавантаження VM, від’єднання сховища (у лабораторії) і перевірте поведінку відновлення та RPO.
- Перевірте бекапи й відновлення з вашими реальними обсягами даних і цільовим RTO.
- План оновлення/відкату: доведіть, що можете рухатися вперед і назад у межах вашого вікна обслуговування. Якщо ні — ви не готові.
Якщо ви залишаєтесь на upstream MySQL, але хочете «Percona-подібної безпеки»
- Припиніть користуватися застарілими гайдами з налаштування. Перевірте значення за замовчуванням для вашої точної версії.
- Зробіть стійкість явною. Встановіть
innodb_flush_log_at_trx_commitіsync_binlogсвідомо; задокументуйте RPO. - Увімкніть спостережуваність. Performance Schema ON, налаштований slow log, автоматизований аналіз digest.
- Побудуйте швидкий рукопис діагностики (план вище) і репетируйте його.
- Тренуйте відновлення. Якщо ви не вмієте відновити — у вас не бекапи, а дорогі файли.
- Захистіть базу від застосунку. Ліміти з’єднань, таймаути, розумні повтори та обмеження швидкості під час інцидентів.
Мінімальна позиція конфігурації «безпечніші налаштування» (концептуально)
Це не повна конфігурація, бо апарат і навантаження важливі. Це позиція: віддавайте пріоритет стійкості, видимості й контрольованій конкурентності перед мікрооптимізаціями.
- Стійкість: безпечні значення флашу за замовчуванням, якщо не відхилено явно.
- Спостережуваність: Performance Schema ON, slow log ON з розумними порогами.
- Конкурентність: примусове обмеження max connections; використання пулів; моніторинг потоків running.
- Реплікація: GTID там, де доречно; row-based реплікація; алерти на відставання.
- Бекапи: автоматизовані, перевірені й відновлювані в межах RTO.
Поширені запитання
Чи є Percona Server «drop-in» заміною для MySQL?
Зазвичай близько, але «drop-in» — обіцянка, яку слід перевірити. Протестуйте плагіни аутентифікації, реплікацію, інструменти бекапу й будь-які краєві SQL-моди, від яких ви залежите.
Чи автоматично Percona Server буде швидшим?
Не автоматично. Ви можете побачити виграші від інструментації й деяких покращень рушія, але більшість продуктивності — це схема + запити + IO. Очікуйте «легше діагностувати», а не «безкоштовного прискорення».
Що означає «безпечніші налаштування» в реальних термінах аварії?
Це означає, що ви менше ймовірності втратите підтверджені дані після збою, менше ймовірності заблокувати себе невидимими очікуваннями блокувань і швидше побачите справжнє вузьке місце.
Чи шкодить увімкнення Performance Schema продуктивності?
Є накладні витрати, але сучасні розгортання MySQL 8 загалом запускають його увімкненим. Вимірюйте для вашого навантаження, але вимикати його, щоб заощадити кілька відсотків і втратити діагностику — зазвичай погана угода.
Чи варто ставити innodb_flush_log_at_trx_commit=2 заради продуктивності?
Тільки якщо ви явно прийняли втрату даних при краху і перевірили, що це означає на вашому сховищі. Багато команд ставлять це «тимчасово» і зберігають роками, поки реальність не накаже платити за це відсотки.
Чи завжди відставання репліки — це проблема бази даних?
Ні. Часто це проблема навантаження (важка міграція), або інфраструктури (IO-зупинки), або схема/індексування, що робить apply дорогим.
Як зрозуміти, чи вузьке місце — блокування чи IO?
Блокування проявляються як очікування в processlist і Performance Schema, плюс довгі транзакції. IO проявляється як підвищений disk await/fsync-зупинки і тиск контрольних точок InnoDB.
Яка найкраща «нудна» практика, щоб зменшити кількість відмов?
Регулярні вправи з відновлення. Якщо ви вмієте надійно й швидко відновити, ви переживете неминучий поганий деплой, подію сховища або людську помилку.
Чи потрібні інструменти Percona, якщо я запускаю Percona Server?
Ні, але екосистема цілісна. Навіть на upstream MySQL інструменти Percona (моніторинг/підходи до бекапів) можуть підвищити операційну зрілість, якщо їх обережно впроваджувати.
Висновок: наступні кроки, які ви можете виконати
Якщо ви хочете менше простоїв — перестаньте ставити MySQL у чорний ящик і перестаньте трактувати налаштування як рису характеру. Незалежно від того, оберете ви upstream MySQL чи Percona Server, переможна стратегія однакова: безпечніша стійкість, контрольована конкурентність і безжальна спостережуваність.
- Заміруйте базу: зафіксуйте змінні, InnoDB status, топ-digest’и, стан реплікації і затримки IO на ОС.
- Виправте великі проблеми першими: регресії запитів, відсутні індекси, шторм з’єднань і довгі транзакції.
- Зробіть стійкість наміреною: встановіть значення флашу/синхронізації бінлогу на основі задокументованого RPO, а не легенд.
- Оберіть дистрибутив за операційними результатами: якщо Percona Server дає вам швидшу діагностику й менше «підводних каменів» у вашому середовищі — приймайте його канареєчним розгортанням.
- Репетируйте відмови: вправи з відновлення й тести краху перемагають оптимізм щоразу.
Найкраща база даних — це та, яка відмовляється так, щоб ви могли швидко зрозуміти і відновити роботу до того, як це помітять ваші клієнти.