Вперше, коли ви це помічаєте, здається, що справа в мережі. Сторінки «випадково» зависають, API-запити таймаутять, а середнє навантаження VPS виглядає як сучасне мистецтво.
Потім ви придивляєтесь і розумієте, що база даних робить те, що бази даних роблять: тихо перетворює дрібні конфігураційні гріхи на значну затримку.
На невеликому VPS «стандартні» налаштування не нейтральні. Це набір припущень для чиєїсь чужої машини: інша ОЗП, інше сховище, інше навантаження, інша толерантність до ризику.
Вибір MySQL або MariaDB на основі інерції пакетного менеджера може дорого коштувати в IOPS, тиску пам’яті та неприємних сюрпризах під час реплікації.
Теза: стандартні налаштування шкодять малим машинам
На VPS база даних — не просто ще один процес. Це процес, що перетворює цикли CPU на очікування, видимі користувачу.
Якщо у вас 1–4 vCPU з помірною ОЗП і спільним бекендом зберігання, різниця між «нормально» і «болісно» часто
полягає в одній стандартній змінній: розмір буфера, налаштування надійності, поведінка fsync або фоновий потік, який правильний для потужного сервера,
але каральний для крихітного.
MySQL і MariaDB достатньо схожі, щоб люди ставились до вибору, як до вибору бренду мінералки. Але внутрішні механізми розходилися
роками, і упаковочні стандарти (особливо в пакетах дистрибутивів) можуть призвести до повільних проблем в уповільненому режимі:
- Занадто малий InnoDB buffer pool → постійні читання, підвищені дискові IOPS і хвостова латентність.
- Надто агресивне скидання → стрибки черги на запис, зависання та «таємничі» таймаути.
- Неправильні SQL-моди або поведінка оптимізатора → плани, що виглядають нормальними, доки таблиця не виросте.
- Припущення про «drop-in заміну» для реплікації чи інструментів → болісні міграції в найгірший момент.
Правильний спосіб вибору нудний: вирішуйте за операційною сумісністю, передбачуваною продуктивністю під вашим навантаженням і шляхом оновлення.
Якщо у вас типовий VPS, що запускає вебдодаток з InnoDB-таблицями, скажу прямо: оберіть движок, який ви зможете впевнено оновлювати й настроювати,
і зробіть стандарти своїми. Ворог не в MySQL чи MariaDB. Ворог — дозволити пакету вирішувати вашу виробничу позицію.
Факти й історія, що важливі в продакшені
Кілька конкретних фактів і контекстних моментів, які пояснюють, чому «вони практично однакові» перестало бути правдою:
- MariaDB відгалузилась від MySQL у 2009 році після побоювань щодо поглинання Sun компанією Oracle. Намір був уніфікації; реальність — розходження.
- MySQL 8.0 прибрав query cache (він був джерелом глобальних мьютексів). MariaDB довше зберігала варіант, і багато дистрибутивів досі постачають конфіги, що його згадують.
- MySQL 8.0 використовує транзакційну словникову структуру всередині InnoDB. MariaDB реалізувала метадані інакше. Це впливає на оновлення, відновлення після збою та інструменти.
- MariaDB представила Aria як заміну MyISAM для внутрішніх тимчасових таблиць і безпеки при збоях. Це може бути корисно, але це ще один рухомий компонент.
- MySQL додав «instant ADD COLUMN» (у багатьох випадках) і покращив онлайн DDL; MariaDB має власну історію онлайн DDL і свої крайні випадки.
- GTID-реалізації відрізняються між MySQL і MariaDB. Вони поділяють акронім, а не повну сумісність. Це важливо, коли ви намагаєтесь переключитись опівночі під час інциденту.
- Стандартні плагіни автентифікації розійшлися (помітно навколо MySQL 8). Ваші драйвери додатків і старі клієнти можуть звернутися на це більше, ніж ви думаєте.
- Обидва оптимізовані під пропускну здатність, а не під ваш VPS — отже фонове скидання і конкуренція потоків можуть перемагати в бенчмарках і створювати спайкову латентність на обмеженому сховищі.
Одна цитата, що досі найкраще підсумовує, чому це важливо:
переказана думка
— Werner Vogels: все рано чи пізно виходить з ладу, тому ви проєктуєте й експлуатуєте з урахуванням збою, а не сподіваєтесь, що його не буде.
Що насправді гальмує базу даних на VPS
«База даних повільна» — це не діагноз. На VPS зазвичай це одна (або кілька) із цих категорій:
1) Затримка сховища і поведінка fsync (тихий вбивця)
Сховище VPS часто мережеве, перенасичене або агресивно кешоване. Ваш бенчмарк може показувати 20k IOPS, але базі потрібна
послідовна латентність, а не епізодні рекорди. InnoDB — машина надійності: він пише redo, скидає і очікує стабільного fsync.
Якщо латентність fsync стрибає, транзакції накопичуються, потоки зупиняються, і ваш додаток починає звинувачувати «базу даних», ніби вона має свідомість.
Найгірше: ваш CPU може бути простоюючим, поки все чекає на сховище. Ви побачите низьке завантаження CPU, високий середній load і чергу потоків у стані «waiting for handler commit».
2) Тиск пам’яті: занадто малий buffer pool + боротьба з кешем сторінок Linux
На маленькому VPS ви не маєте ОЗП, щоб її марнувати. Якщо innodb buffer pool занадто малий, ви інтенсивно перетасовуєте сторінки й весь час читаєте з диска.
Якщо він надто великий, ОС починає агресивно звільняти сторінки, сервер починає свопити, і тепер повільні всі сервіси, включаючи журнали бази даних, бо ядро в поганому настрої.
«Правильний» buffer pool не формула «встановити 80%». Це залежить від того, що ще працює на машині, який розмір робочого набору
і чи ви цінуєте стабільну латентність понад піковий показник кеш-хітів.
3) Параметри конкуренції, що не відповідають кількості vCPU
І MySQL, і MariaDB можуть запускати фонові потоки й шаблони конкуренції, які підходять для 16 ядер, але безглузді на 2.
Якщо ви бачите contention на мютексах, багато контекстних перемикань або накладні витрати планування потоків, вузьке місце не в SQL.
Воно в оркестровці ресурсів.
4) Плани запитів, що «працювали вчора»
На маленьких наборах даних погані індекси ховаються в кеші. На VPS щойно набір даних перестає вміщатися в ОЗП,
відсутній складний індекс перетворюється на випадковий I/O і slow query log заповнюється соромом.
Відмінності в поведінці оптимізатора між MySQL і MariaDB можуть визначити, які запити першими впадуть у прірву.
Жарт №1: Якщо ви не можете відтворити уповільнення в staging, вітаю — ви зробили staging, який чудово бреше.
Практичні відмінності: MySQL 8 проти MariaDB сьогодні
Поговоримо про вибори, що змінюють результати на VPS, а не про ідеологічні дебати.
Упакування та «стандартні» конфігурації — це половина битви
У сімействах Debian/Ubuntu встановлення mysql-server може дати вам MariaDB залежно від дистрибутива й версії.
У деяких дистрибутивах MariaDB постачається з фрагментами конфігів, що включають застарілі параметри або консервативні значення.
Пакети спільноти MySQL часто мають свої стандарти, які передбачають, що ви настроюватимете під своє залізо.
Небезпечна схема: ви думаєте, що обрали «MySQL», але насправді обрали «те, що тестували підтримувачі дистрибутива для загальної сумісності».
Це може бути правильним для «воно запускається», і неправильним для «воно залишається швидким».
Сумісність реплікації та інструментів експлуатації
Якщо ви використовуєте реплікацію, вибір має ще більше значення.
MariaDB має фічі, яких немає в MySQL, і навпаки. Але велика підводна міна — GTID-набори й семантика не взаємозамінні.
Якщо ви плануєте пізніше перемикатися між движками, це буде проєкт міграції, а не просто оновлення пакета.
Для однодоменної VPS реплікація все одно може бути присутня (репліки для читання, репліки для міграції, DR).
Якщо ви колись захочете швидко створити нову репліку, «сумісні GTID і формати binlog» — це не миле дрібничка.
Продуктивність — це не «хто швидший», а «хто передбачуваніший»
Будь-хто може бути швидким. Обидва можуть бути повільними. Практичне питання: хто дає найменше несподіванок під тиском,
з менш заплутаними семантиками оновлень і конфігурації, на вашій ОС?
- Якщо вам потрібні фічі MySQL 8 (сучасна робота з JSON, зміни словника даних, екосистемна сумісність) — обирайте MySQL і налаштовуйте його правильно.
- Якщо у вашому дистрибутиві MariaDB — дефолт і ваш стек вже сумісний — MariaDB підходить, просто проведіть аудит значень за замовчуванням і приберіть спадщину.
- Якщо ви плануєте переміщення між managed-сервісами і self-hosting, сумісність MySQL може зменшити тертя. Але не припускайте; перевіряйте драйвери й SQL-моди.
Швидкий план діагностики (перший/другий/третій)
Ось що робити, коли VPS повільний і вам потрібні відповіді, поки користувачі ще не почали писати поему в службу підтримки.
Перший: доведіть, чи ви CPU-bound, I/O-bound або memory-bound
- Перевірте очікування сховища і чергу виконання:
iostat,vmstat. - Перевірте тиск пам’яті і своп:
free,sar(якщо доступно). - Перевірте стани потоків MySQL/MariaDB: processlist / performance schema / лічильники статусу.
Другий: ідентифікуйте головне очікування всередині бази
- Показники InnoDB: к-ть попадань у буфер, очікування журналу, поведінка checkpoint age.
- Повільні запити: увімкніть slow query log ненадовго, якщо безпечно, або використайте наявні логи.
- Блокування: шукайте транзакції, що чекають рядкових або метаданих-блокувань.
Третій: вирішіть, чи виправлення — запит/індекс, конфіг або сховище
- Якщо дискова затримка висока і buffer pool крихітний: спочатку налаштуйте пам’ять і скидання.
- Якщо диск в порядку, але час запитів стрибає: дивіться плани й індекси.
- Якщо все «добре», але латентність рвануста: дивіться на поведінку fsync, фонове скидання і кредитні обмеження провайдера.
Практичні завдання: команди, виводи, рішення
Це реальні завдання, які можна виконати на Linux VPS. Кожне включає команду, приклад виводу, що це означає, і рішення, яке слід прийняти.
Виконуйте їх як чекліст під час інциденту або як базовий аудит, коли ви успадковуєте сервер, який «завжди таким був».
Завдання 1: Підтвердити, яку базу ви реально запускаєте
cr0x@server:~$ mysql --version
mysql Ver 15.1 Distrib 10.11.6-MariaDB, for debian-linux-gnu (x86_64) using EditLine wrapper
Що це означає: Це MariaDB 10.11, а не Oracle MySQL. Люди плутають клієнт і сервер, але цей вивід зазвичай дає чітку підказку.
Рішення: Припиніть писати «MySQL» в тікетах. Якщо плануєте налаштування або фічі специфічні для MySQL, повторно перевірте походження пакетів і можливості сервера.
Завдання 2: Підтвердити демон сервера і джерело пакета
cr0x@server:~$ systemctl status mariadb --no-pager
● mariadb.service - MariaDB 10.11.6 database server
Loaded: loaded (/lib/systemd/system/mariadb.service; enabled; preset: enabled)
Active: active (running) since Mon 2025-12-29 08:12:31 UTC; 2h 14min ago
Docs: man:mariadbd(8)
https://mariadb.com/kb/en/library/systemd/
Main PID: 742 (mariadbd)
Status: "Taking your SQL requests now..."
Tasks: 41 (limit: 2275)
Memory: 1.2G
CPU: 38min 12.331s
Що це означає: Ім’я сервісу та основний бінарник ідентифікують форк. Також зверніть увагу на використання пам’яті: на маленькому VPS 1.2G може вже бути майже весь хост.
Рішення: Якщо у вас мало пам’яті, негайно перейдьте до налаштування buffer pool і лімітів з’єднань/потоків перед оптимізацією запитів.
Завдання 3: Перевірити ОЗП, своп і чи ви вже програєте
cr0x@server:~$ free -h
total used free shared buff/cache available
Mem: 3.8Gi 3.1Gi 110Mi 62Mi 640Mi 210Mi
Swap: 2.0Gi 1.4Gi 600Mi
Що це означає: Іде своп. «available» ледь-ледь. Ядро виконує звільнення і БД залежатиме непередбачувано.
Рішення: Зменшіть пам’ять (buffer pool завеликий, надто багато з’єднань, великі тимчасові таблиці) або додайте ОЗП. Налаштування без усунення свопу — це показова продуктивність.
Завдання 4: Визначити, чи ви зараз I/O-bound
cr0x@server:~$ iostat -x 1 3
Linux 6.1.0-18-amd64 (server) 12/29/2025 _x86_64_ (2 CPU)
avg-cpu: %user %nice %system %iowait %steal %idle
12.00 0.00 6.00 28.00 0.50 53.50
Device r/s w/s rkB/s wkB/s rrqm/s wrqm/s %util await
vda 110.0 240.0 4200.0 9200.0 0.0 2.0 96.0 18.7
Що це означає: %util близько 100 і await ≈ 19ms: сховище насичене і повільне. Саме так з’являються «випадкові» таймаути.
Рішення: Зменшіть запис (налаштування скидання, binlog sync, батчинг транзакцій), підвищте хітрейт кешу або перемістіть на швидше сховище. Також перевірте ліміти провайдера на «burst».
Завдання 5: Перевірити, чи файловій системі не бракує місця
cr0x@server:~$ df -h /var/lib/mysql
Filesystem Size Used Avail Use% Mounted on
/dev/vda1 50G 46G 2.0G 96% /
Що це означає: 96% використано — це не «добре». InnoDB потребує місця для тимчасових файлів, логів і внутрішніх операцій.
Рішення: Звільніть місце негайно (логи, бекапи, старі binlog) або розширте диск. Не чекайте на драму, близьку до «диск заповнений».
Завдання 6: Визначити каталог даних і перевірити подвійний запис/редо-контекст
cr0x@server:~$ mysql -e "SHOW VARIABLES LIKE 'datadir'; SHOW VARIABLES LIKE 'innodb_doublewrite'; SHOW VARIABLES LIKE 'innodb_flush_log_at_trx_commit';"
+---------------+---------------------+
| Variable_name | Value |
+---------------+---------------------+
| datadir | /var/lib/mysql/ |
+---------------+---------------------+
+-------------------+-------+
| Variable_name | Value |
+-------------------+-------+
| innodb_doublewrite| ON |
+-------------------+-------+
+--------------------------------+-------+
| Variable_name | Value |
+--------------------------------+-------+
| innodb_flush_log_at_trx_commit | 1 |
+--------------------------------+-------+
Що це означає: Надійність встановлена на найбезпечніші значення. На дешевому VPS-сховищі це може означати велику кількість очікувань fsync.
Рішення: Для критичних даних тримайте так. Для систем, які можна відтворити з черги, розгляньте innodb_flush_log_at_trx_commit = 2, але тільки з явним прийняттям ризику.
Завдання 7: Перевірити розмір buffer pool відносно ОЗП
cr0x@server:~$ mysql -e "SHOW VARIABLES LIKE 'innodb_buffer_pool_size';"
+-------------------------+------------+
| Variable_name | Value |
+-------------------------+------------+
| innodb_buffer_pool_size | 134217728 |
+-------------------------+------------+
Що це означає: 128MiB buffer pool на сервері з 4GiB — майже напевно замало, якщо тільки набір даних не крихітний.
Рішення: Збільшіть його обачно (часто 1–2GiB на 4GiB VPS, залежно від інших сервісів). Потім стежте за свопом і ризиком OOM.
Завдання 8: Перевірити ефективність buffer pool і частку читань з диска
cr0x@server:~$ mysql -e "SHOW GLOBAL STATUS LIKE 'Innodb_buffer_pool_read%';"
+---------------------------------------+-----------+
| Variable_name | Value |
+---------------------------------------+-----------+
| Innodb_buffer_pool_read_requests | 982334112 |
| Innodb_buffer_pool_reads | 18399244 |
+---------------------------------------+-----------+
Що це означає: Деякі читання з диска нормальні. Але якщо Innodb_buffer_pool_reads швидко зростає під час піку, ви втрачаєте кеш або індекси.
Рішення: Якщо читання з диска корелюють з пиками затримки, збільшіть buffer pool (якщо є пам’ять) і/або виправте індекси. Не гадати: корелюйте з часовими вікнами.
Завдання 9: Подивитися, на що сервер вважає, що чекає (швидка тріаж)
cr0x@server:~$ mysql -e "SHOW FULL PROCESSLIST;" | head -n 15
Id User Host db Command Time State Info
112 app 10.0.1.25:53142 prod Query 12 Waiting for handler commit UPDATE orders SET status='paid' WHERE id=?
118 app 10.0.1.25:53159 prod Query 11 Waiting for handler commit INSERT INTO payments(order_id, ...) VALUES (...)
121 app 10.0.1.25:53168 prod Query 9 Waiting for handler commit UPDATE inventory SET ...
130 app 10.0.1.25:53201 prod Sleep 55 NULL
Що це означає: «Waiting for handler commit» часто вказує на тиск redo log/fsync (надійність + латентність сховища).
Рішення: Зосередьтеся на шляху диска/fsync: розмір redo log, політика скидання, продуктивність сховища, налаштування binlog sync.
Завдання 10: Перевірити конфігурацію slow query log (увімкнути тимчасово, якщо потрібно)
cr0x@server:~$ mysql -e "SHOW VARIABLES LIKE 'slow_query_log'; SHOW VARIABLES LIKE 'slow_query_log_file'; SHOW VARIABLES LIKE 'long_query_time';"
+----------------+-------+
| Variable_name | Value |
+----------------+-------+
| slow_query_log | OFF |
+----------------+-------+
+---------------------+--------------------------+
| Variable_name | Value |
+---------------------+--------------------------+
| slow_query_log_file | /var/log/mysql/slow.log |
+---------------------+--------------------------+
+-----------------+-------+
| Variable_name | Value |
+-----------------+-------+
| long_query_time | 10.000000 |
+-----------------+-------+
Що це означає: Він вимкнений і long_query_time високий. На VPS запит у 1–2 с вже може зіпсувати хвостову латентність.
Рішення: Тимчасово увімкніть із нижчим порогом у контрольованому вікні, потім вимкніть або організуйте ротацію, щоб уникнути надмірного I/O.
Завдання 11: Перевірити бінарне логування та налаштування синхронізації (аудит write amplification)
cr0x@server:~$ mysql -e "SHOW VARIABLES LIKE 'log_bin'; SHOW VARIABLES LIKE 'sync_binlog'; SHOW VARIABLES LIKE 'binlog_format';"
+---------------+-------+
| Variable_name | Value |
+---------------+-------+
| log_bin | ON |
+---------------+-------+
+---------------+-------+
| Variable_name | Value |
+---------------+-------+
| sync_binlog | 1 |
+---------------+-------+
+---------------+-------+
| Variable_name | Value |
+---------------+-------+
| binlog_format | ROW |
+---------------+-------+
Що це означає: Безпечно, але дорого. sync_binlog=1 додає fsync-навантаження. На крихкому сховищі це може домінувати.
Рішення: Якщо ви не реплікуєте і не потребуєте PITR з binlog, розгляньте відключення binlog. Якщо потрібен, подумайте про sync_binlog=100 (обмін ризиком) і задокументуйте радіус ураження.
Завдання 12: Перевірити поведінку тимчасових таблиць (приховане використання диска)
cr0x@server:~$ mysql -e "SHOW GLOBAL STATUS LIKE 'Created_tmp%'; SHOW VARIABLES LIKE 'tmp_table_size'; SHOW VARIABLES LIKE 'max_heap_table_size';"
+-------------------------+---------+
| Variable_name | Value |
+-------------------------+---------+
| Created_tmp_disk_tables | 182331 |
| Created_tmp_files | 44219 |
| Created_tmp_tables | 903112 |
+-------------------------+---------+
+----------------+----------+
| Variable_name | Value |
+----------------+----------+
| tmp_table_size | 16777216 |
+----------------+----------+
+---------------------+----------+
| Variable_name | Value |
+---------------------+----------+
| max_heap_table_size | 16777216 |
+---------------------+----------+
Що це означає: Багато тимчасових таблиць потрапляють на диск, а ліміти малі (16MiB). Операції сортування/групування битимуть по сховищу.
Рішення: Обережно збільшіть ці значення (вони потенційно на кожне з’єднання), і виправте запити, що створюють великі тимчасові таблиці. На VPS дискові тимчасові таблиці — міни латентності.
Завдання 13: Перевірити кількість підключень і чи немає thrashing потоків
cr0x@server:~$ mysql -e "SHOW GLOBAL STATUS LIKE 'Threads_connected'; SHOW GLOBAL STATUS LIKE 'Threads_running'; SHOW VARIABLES LIKE 'max_connections';"
+-------------------+-------+
| Variable_name | Value |
+-------------------+-------+
| Threads_connected | 312 |
+-------------------+-------+
+-----------------+-------+
| Variable_name | Value |
+-----------------+-------+
| Threads_running | 46 |
+-----------------+-------+
+-----------------+-------+
| Variable_name | Value |
+-----------------+-------+
| max_connections | 500 |
+-----------------+-------+
Що це означає: 312 з’єднань на маленькому VPS — часто самошкода. Навіть якщо вони сплячі, витрати пам’яті й управління потоками накопичуються.
Рішення: Виправте пулінг на рівні додатка, зменшіть max_connections і підберіть thread cache. Якщо вам потрібно сотні підключень, ймовірно, потрібна більша машина або проксі-шар.
Завдання 14: Перевірити конфігурацію InnoDB log (тиск чекпоінтів проти часу відновлення)
cr0x@server:~$ mysql -e "SHOW VARIABLES LIKE 'innodb_log_file_size'; SHOW VARIABLES LIKE 'innodb_log_files_in_group';"
+---------------------+----------+
| Variable_name | Value |
+---------------------+----------+
| innodb_log_file_size| 50331648 |
+---------------------+----------+
+--------------------------+-------+
| Variable_name | Value |
+--------------------------+-------+
| innodb_log_files_in_group| 2 |
+--------------------------+-------+
Що це означає: Редо-логи загалом ~96MiB — мало для write-heavy навантажень. Це може примушувати часті чекпоінти і більше фонового скидання.
Рішення: Збільшіть розмір логів, якщо у вас інтенсивні записи і сховище нестабільне, збалансуйте з часом відновлення. Плануйте зміну правильно (потребує перезапуску і обробки файлів).
Завдання 15: Підтвердити реальні конфігураційні файли (не налаштовуйте неправильний файл)
cr0x@server:~$ mysql -e "SHOW VARIABLES LIKE 'pid_file'; SHOW VARIABLES LIKE 'log_error';"
+---------------+------------------------+
| Variable_name | Value |
+---------------+------------------------+
| pid_file | /run/mysqld/mysqld.pid |
+---------------+------------------------+
+---------------+--------------------------+
| Variable_name | Value |
+---------------+--------------------------+
| log_error | /var/log/mysql/error.log |
+---------------+--------------------------+
Що це означає: Тепер ви знаєте, де шукати діагностику запуску і можете підтвердити, який екземпляр працює.
Рішення: Відкрийте error log і перевірте відсутність попереджень про ігноровані змінні (поширено при копіюванні конфігів між MySQL і MariaDB).
Завдання 16: Переглянути error log на предмет ігнорованих налаштувань або підказок про відновлення після збою
cr0x@server:~$ sudo tail -n 40 /var/log/mysql/error.log
2025-12-29 08:12:30 0 [Note] mariadbd: ready for connections.
2025-12-29 09:41:02 0 [Warning] 'query_cache_size' is deprecated and will be removed in a future release.
2025-12-29 10:07:11 0 [Warning] Aborted connection 118 to db: 'prod' user: 'app' host: '10.0.1.25' (Got timeout reading communication packets)
Що це означає: Застарілі параметри можуть ще працювати, але вказують на дрейф конфігурації. Aborted connections можуть бути таймаутами додатка або зупинками сервера.
Рішення: Приберіть застарілі налаштування і розглядайте aborted connections як симптом: корелюйте з очікуванням сховища і зависаннями запитів.
Три корпоративні міні-історії (те, що не викладають у Slack)
Міні-історія 1: Інцидент через неправильне припущення
Компанія експлуатувала набір невеликих регіональних VPS для затребуваних латентністю навантажень. Усі називали шар бази «MySQL».
Нові вузли створювалися з образу дистрибутива, і ніхто цього не ставив під сумнів. Чому б і ні? Додаток підключався, таблиці були, реплікація «працювала».
Під час вікна обслуговування вони додали репліку в інший регіон і планували швидке опрацювання відмови.
Дриль провалився нудним, але катастрофічним способом: GTID-інструменти очікували семантику MySQL і повідомили про конфлікт стану.
Інженер на чергуванні спробував «полагодити» команди, що були правильні для одного движка й тонко неправильні для іншого.
Результат не був миттєвою втратою даних. Було гірше: часткова відмова з додатком, який вважав, що пише в primary,
тоді як частина трафіку потрапила на вузол, що не реплікувався коректно. Інцидент тривав достатньо довго, щоб на поверхні з’явилися невідповідності для клієнтів.
Постмортем мав один рядок, що мав значення: припущення, що «MariaDB — drop-in заміна MySQL», було прийняте за факт,
тож ніхто не документував, який движок насправді розгорнутий. Це припущення поширилося в автоматизацію, моніторинг і рукописи.
Виправлення було нудним і ефективним: інвентаризація кожного вузла, стандартизація движка/версії в середовищі і додавання перевірки запуску в pipeline розгортання,
яка стверджує очікуваний флер сервера і критичні змінні. Вони припинили покладатися на відчуття і почали покладатися на факти.
Міні-історія 2: Оптимізація, що дала зворотний ефект
Інша команда гналася за латентністю записів на бюджетній VPS-платформі. Вони прочитали про налаштування надійності й вирішили «прискорити»
шляхом послаблення поведінки підтвердження комітів. Зміна була невеликою, графіки виглядали краще, і команда тихо святкувала — бо гучні святкування спокушають долю.
Через два тижні хост мав незапланований ребут. База відновилася, додаток запрацював, і всі подумали, що їм пощастило.
Потім у черзі підтримки з’явилися повідомлення про відсутні недавні оновлення. Не величезні обсяги, але достатньо, щоб бути реальними.
Система технічно поводилася, як налаштовано: транзакції, підтверджені клієнту, не обов’язково були на стабільному сховищі в момент підтвердження.
Саме цього вони й просили. Проблема була не в ручці; проблема була в тому, що вони змінили контракт надійності без зміни очікувань продукту.
Відкат був миттєвим. Довгострокова «оптимізація» перетворилась на реальний інженерний план:
тримати сувору надійність для критичних таблиць, пропускати менш важливі записи через чергу з ідемпотентністю
і перестати використовувати налаштування надійності бази як замінник архітектури.
Міні-історія 3: Нудна але правильна практика, що врятувала день
Команда SaaS експлуатувала MariaDB на скромних VPS. Нічого складного. Але у них була одна звичка: щотижневі відпрацювання відновлення.
Не теоретичні відновлення. Справжні відновлення на тестовий VPS з перевірками диму додатка і базовою перевіркою контрольних сум.
Одного дня розробник задеплоїв міграцію, що привела до патерну запиту, який створював масивні тимчасові таблиці на диску.
База не «впала». Вона просто ставала дедалі повільнішою, як заповнювався диск. Зрештою він досяг 100% і сервіс впав.
Негайна відповідь була безладною: звільнити місце, вбити найгірші запити, відкотити додаток. Але кілька таблиць були частково оновлені
до заповнення диска і логіка відкату не була чистою. Потрібно було відновитися до точки перед міграцією.
Практика відновлення окупилася. Команда вже знала кроки відновлення, межі часу відновлення і одну конфігураційну опцію,
яку завжди пропускали. Вони відновили, перевірили, відтворили лише безпечну підмножину змін і повернулись онлайн з мінімальною драмою.
Підсумкова дія була не «будь обережніший». Вона була конкретною: додати перевірки планів запитів для шляху міграції, моніторити коефіцієнт spill тимчасових таблиць
і продовжувати нудні відпрацювання відновлення, поки вони не врятують вам вихідні дні.
Поширені помилки: симптом → причина → виправлення
1) Симптом: низький CPU, високий середній load, випадкові таймаути
Причина: I/O wait і насичення сховища; потоки заблоковані на fsync/скиданні або повільних читаннях.
Виправлення: Використайте iostat -x для підтвердження високого await/%util. Збільште buffer pool, якщо він недостатній, зменшіть write amplification (binlog sync, політика скидання) і розгляньте перехід на краще сховище.
2) Симптом: продуктивність падає після «невеликого» збільшення трафіку
Причина: Робочий набір більше не вміщується в buffer pool; тепер ви виконуєте випадкові читання з диска.
Виправлення: Виміряйте співвідношення buffer pool reads / requests. Додайте відсутні індекси, збільшіть buffer pool і перевірте, що ви не почали свопити.
3) Симптом: раптові зупинки під час сильних хвиль записів
Причина: Тиск чекпоінтів (redo логи занадто малі) або агресивне скидання у взаємодії з повільним сховищем.
Виправлення: Збільште ємність redo логів за потреби та налаштуйте поведінку скидання. Перевірте processlist на стани типу «Waiting for handler commit».
4) Симптом: використання пам’яті зростає, поки сервер не починає свопити
Причина: Занадто багато з’єднань, великі буфери на з’єднання, ріст тимчасових таблиць або buffer pool встановлено занадто високо для машини.
Виправлення: Обмежте з’єднання, впровадьте пулінг, зменшіть буфери на з’єднання і підберіть buffer pool за розміром. Перевіряйте free -h і Threads_connected.
5) Симптом: інструменти реплікації/відмови поводяться дивно
Причина: Припущення, що MySQL і MariaDB GTID/семантика реплікації співпадають; змішані версії/форки.
Виправлення: Стандартизувати движок у топології або використовувати явні плани сумісності. Не змішуйте без тестованого рукопису.
6) Симптом: «Стало повільніше після оновлення»
Причина: Зміни в поведінці оптимізатора, SQL-моди або конфігураційні змінні більше не дійсні; також можливий регрес через інші дефолти.
Виправлення: Зробіть diff ключових змінних до/після оновлення, перевірте error log на ігноровані налаштування і повторно базуйтеся на зразках повільних запитів і EXPLAIN-планах.
Жарт №2: База даних не «випадково» стала повільною. Вона просто виражає свої почуття щодо ваших стандартних налаштувань.
Контрольні списки / покроковий план
План A: У вас зараз повільний VPS
- Стабілізувати: підтвердьте місце на диску (
df -h), зупиніть найгірші запити і переконайтеся, що немає сильного свопінгу. - Класифікувати: запустіть
iostat -xіfree -h. Вирішіть: I/O-bound, memory-bound чи CPU-bound. - Топ-очікування: processlist на commit waits/locks; швидка сесія slow log якщо безпечно.
- Швидкі правки: поправте buffer pool якщо крихітний; зменшіть з’єднання; вирішіть проблеми spill тимчасових таблиць.
- Ризикові налаштування: змінюйте налаштування надійності лише з явним погодженням і планом відкату.
- Валідація: вимірюйте p95 латентність і await сховища після змін, а не лише середній QPS.
План B: Ви вибираєте між MySQL і MariaDB для нового VPS
- Визначте потреби екосистеми: драйвери клієнтів, особливості ORM, вирівнювання з managed-сервісами, потреби реплікації.
- Обирайте один движок на середовище: не змішуйте «бо колись працювало».
- Базові конфіги: встановіть buffer pool, розміри логів, ліміти з’єднань і політику slow log свідомо.
- План оновлень: тестуйте мажорні/мінорні оновлення і перевірку дійсності конфігів у staging, що максимально нагадує VPS-сховище.
- Побудуйте спостережуваність: збирайте slow query логи (з ротацією), базові метрики ОС і лічильники статусу БД.
План C: Ви вже експлуатуєте один і хочете переключитись
- Не сприймайте це як заміну пакета: ставтесь до цього як до міграції з тестуванням сумісності.
- Інвентаризуйте фічі: SQL-моди, плагіни автентифікації, формат реплікації, збережені процедури, тригери, поведінку charset/collation.
- Сухий прогін відновлення/міграції: практикуйте експорт/імпорт або підхід логічної реплікації на тестовому вузлі.
- Переключення з відкатом: визначте точні критерії відкату (рівні помилок, lag реплікації, перевірки даних) і тримайте старий primary у режимі read-only певний час.
Питання й відповіді
1) Чи MariaDB швидша за MySQL на VPS?
Іноді, для конкретних навантажень і версій. Але на VPS більший показник — чи ваші дефолти відповідають ОЗП і латентності сховища.
Будь-який движок може бути швидким; будь-який може бути гальмом.
2) Чому «стандартна інсталяція» часто відчувається повільною на малих серверах?
Дефолти орієнтовані на широку сумісність і надійність. На обмеженому сховищі безпечна поведінка fsync і малі кеші можуть перетворитись на часті затримки.
Потрібно правильно підібрати пам’ять і зменшити зайву write amplification.
3) Чи можна налаштуваннями компенсувати повільне сховище VPS?
Ви можете зменшити шкоду (більший buffer pool, менше fsync, менше тимчасових таблиць на диску). Але ви не зможете налаштуваннями позбутися жахливої латентності сховища.
Якщо iostat показує високий await при помірному навантаженні, реальне рішення — апгрейд сховища або зміна провайдера.
4) Чи варто змінити innodb_flush_log_at_trx_commit на 2?
Тільки якщо ви розумієте і приймаєте компроміс надійності: ви можете втратити приблизно секунду транзакцій при збою.
Для багатьох веб-застосунків з чергами й ідемпотентністю це прийнятно. Для фінансових або систем запису правочинів зазвичай ні.
5) Чи безпечно відключати бінлог?
Якщо ви не реплікуєте і не використовуєте binlog для відновлення у часі, відключення може зменшити навантаження на запис.
Якщо вам потрібен PITR або репліки, тримайте його увімкненим і налаштовуйте sync_binlog з документованим ризиком.
6) Чому в processlist так багато «Sleeping» з’єднань?
Зазвичай це пулінг додатка або витоки з’єднань. Sleeping — не безкоштовний стан: пам’ять і управління потоками накладають витрати.
Виправте поведінку пулінгу і обмежте max_connections, щоб дисциплінувати використання.
7) Чи можна міксувати MySQL primary з MariaDB репліками (або навпаки)?
Іноді в обмежених конфігураціях, але це крихке і залежить від версій. Для продакшену припускайте «ні», якщо у вас немає тестованого, документованого
і постійно валідуємого плану сумісності реплікації. Це не місце для сюрпризів.
8) Який єдиний найкращий параметр для продуктивності на VPS?
innodb_buffer_pool_size правильно підібраний під вашу ОЗП і навантаження, у поєднанні з відсутністю свопу на машині.
Після цього найкращий «параметр» — зазвичай «додайте правильний індекс».
9) Як зрозуміти, проблема в запитах чи в конфігурації?
Якщо iostat показує високий await і читання InnoDB з диска зростають під час піку, швидше за все, ви обмежені кешем/індексами.
Якщо processlist показує очікування комітів і строгий binlog sync, проблема, ймовірно, у fsync/write-amplification.
10) Чи варто використовувати MyISAM/Aria заради швидкості на VPS?
Для таблиць додатка: майже ніколи ні. InnoDB дає потрібну безпеку при збоях і поведінку конкурентності.
Заміна движка заради «швидкості» зазвичай просто переміщує біль у відновлення й цілісність даних.
Наступні кроки, які можна зробити цього тижня
Якщо ваш VPS із базою повільний, не починайте з релігії движка. Почніть з вимірів, потім усуньте очевидні самостворені рани.
- Визначте движок і версію, який ви реально запускаєте, і задокументуйте це в runbook.
- Зніміть базову інформацію про ОС: зафіксуйте
free -h,df -hіiostat -xв нормальних і пікових періодах. - Підійміть innodb buffer pool під розмір ОЗП і обмежте кількість з’єднань, щоб припинити боротьбу з ядром.
- Аудит write amplification (binlog, sync налаштування, політика комітів) і чітко визначте контракт надійності.
- Короткочасно увімкніть slow query лог (з ротацією) і виправте головні порушники індексами й змінами запитів.
- Відпрацюйте відновлення на тестовий VPS. Не тому, що це весело. Тому що колись це стане необхідністю і вам знадобиться м’язова пам’ять.
Обирайте MySQL або MariaDB на основі сумісності й шляху оновлення. Потім зробіть їхні дефолти своїми.
Ваш VPS перестане «випадково» гальмувати. Він стане передбачувано швидким — і це єдина швидкість, яка має значення в продакшені.