MySQL vs MariaDB: затримки оформлення в WooCommerce — одна настройка вирішує, інша лише маскує

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

Оформлення замовлення має бути нудним. Натиснув «Оформити замовлення», платіж пройшов, квитанція надійшла, усі йдуть додому. Коли оформлення триває 6–20 секунд (або таймаутиться), рідко це «WordPress такий WordPress». Зазвичай це база даних робить саме те, що ви їй наказали — просто не те, чого ви хотіли.

Я бачив, як команди тижнями міняли MySQL на MariaDB (або назад), додавали CPU, кешували сторінки, які не можна кешувати, навіть звинувачували платіжні шлюзи. А потім одна настройка InnoDB змінювала все й затримки зникали. Підступ у тому, що існує інша настройка, яку люди люблять змінювати, і вона лише маскує проблему — поки не обернеться корумпованими очікуваннями та нічними відновленнями.

Як насправді виглядає затримка оформлення в продукції

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

  • Перерахунок сум корзини та податків.
  • Вставка рядка замовлення (а іноді й повторні оновлення кілька разів).
  • Зменшення запасів і вставки елементів замовлення.
  • Оновлення метаданих клієнта/сесії.
  • Плагін оплати записує логи, додає метадані, можливо виконує віддалені виклики.
  • Транзакційні листи ставляться в чергу або відправляються.

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

  • Високий TTFB на /checkout або /?wc-ajax=checkout.
  • Сплески в «Threads running».
  • Час очікування блокувань в InnoDB.
  • CPU не обов’язково зайнятий повністю (база чекає на I/O).
  • Платежі успішні, але сторінка підтвердження зависає (класика: веб чекає на commit БД, шлюз вже зняв гроші).

Операційне формулювання: оформлення — це ваш шлях запису. Ваш шлях запису — це ваша пробірка правдивості. Кеші можуть багато чого приховати; вони не приховають затримки commit назавжди.

Два налаштування: одне лікує, інше маскує

Налаштування, що справді вирішує затримки оформлення (у більшості випадків): ємність redo-журналу

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

Підхід MySQL 8+ (переважний): налаштуйте innodb_redo_log_capacity.

Підхід MariaDB і старіших MySQL: налаштуйте innodb_log_file_sizeinnodb_log_files_in_group, якщо потрібно), розуміючи операційні наслідки.

Чому це саме «вирішення»: воно зменшує примусовий тиск контрольних точок під час сплесків записів. Воно не хитрує з надійністю; воно дозволяє InnoDB пакетувати роботу інтелектуально.

Налаштування, яке люди змінюють і яке здебільшого маскує проблему: перемикач fsync/надійності

Плацебо з ефектом:

  • innodb_flush_log_at_trx_commit (встановлений у 2 або 0)
  • іноді в парі з sync_binlog, встановленим у низьке значення (наприклад 0)

Так, це може прискорити оформлення, бо ви припиняєте платити повну вартість fsync за транзакцію. Але це не виправлення продуктивності; це компроміс надійності. Під час збою або втрати живлення ви можете втратити підтверджені транзакції (або отримати неконсистентну реплікацію, якщо бінлог теж ненадійний). Це не «налаштування», це вибір, який інцидент ви готові терпіти.

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

Коли це обернеться проблемою: будь-що з реальними грошима, реальним запасом, поверненнями коштів або регуляторними очікуваннями. А це більшість магазинів WooCommerce, які платять зарплати.

Жарт №1: Встановити innodb_flush_log_at_trx_commit=0 — це як зняти ремінь безпеки, лише тому що він морщитиме сорочку.

Як «лікування» і «маскування» виглядають на графіках

Коли ємність redo-журналу занадто мала, ви часто побачите:

  • Сплески записів на диск і очікувань fsync.
  • Вікно контрольної точки InnoDB, що досягає стелі.
  • Затримку оформлення, що корелює з фоновим скиданням сторінок.

Коли ви «маскуєте» це за допомогою innodb_flush_log_at_trx_commit=2, ви побачите покращення p95 — але ви не вирішили тиск скидання. Ви просто відклали його й зменшили частоту fsync. Під тривалим навантаженням затримки повернуться в іншій формі (або з’являться як лаг реплікації, час відновлення та неприємні розмови).

MySQL vs MariaDB: де різниці мають значення

Для WooCommerce питання не «що в загальному швидше». Питання — «що більш передбачувано відмовляє під моїм навантаженням, з моїми плагінами, на моєму сховищі». MySQL і MariaDB мають спільне походження, але відійшли настільки, що «drop-in replacement» — це маркетинг, а не інженерія.

1) Журнал редо та поведінка контрольних точок: нудне, але важливе

MySQL 8 ввів innodb_redo_log_capacity, що операційно зручніше, ніж старий танець «зупинити сервер, перемістити ib_logfile*, перезапустити». У MariaDB досі часто використовують innodb_log_file_size (залежно від версії), і операційний шлях може бути більш ручним.

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

2) Обробка потоків при конкуренції: плюси thread pool у MariaDB

MariaDB пропонує пул потоків у деяких збірках/редакціях, що може стабілізувати продуктивність при великій кількості короткочасних з’єднань. WooCommerce за PHP-FPM може створювати хаотичний патерн з’єднань, якщо ви не використовуєте постійні з’єднання (а часто не варто).

MySQL також покращував обробку конкуренції з часом, але якщо ваша проблема — «занадто багато з’єднань/потоків», а не I/O-стали, пул потоків MariaDB може бути практичним плюсом.

3) Планувальник запитів та інструменти моніторингу: інструменти впливають на результат

Коли ви діагностуєте затримки оформлення, вам потрібна надійна видимість очікувань, блокувань і “гарячих” запитів. Performance schema та sys schema MySQL 8 зазвичай чудові для цієї роботи. Інструментування MariaDB відрізняється; можливо, доведеться більше покладатися на information_schema, статус інженера та цільові slow-логи.

4) Реплікація та значення за замовчуванням: не припускайте паритету

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

5) Реальний вирішальний фактор: ваше сховище і реальність fsync

Обидва рушії можуть бути швидкими на хорошому сховищі і катастрофічними на поганому. NVMe з адекватною політикою кешування записів — інша реальність порівняно з мережею зі змінною латентністю. Затримка оформлення часто — це історія про fsync на сумному диску.

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

  • Факт 1: MariaDB відгалузився від MySQL після придбання Sun компанією Oracle, і сумісність була «переважно», а не «завжди». У тому «переважно» і живуть відмови.
  • Факт 2: InnoDB не спочатку був «рушієм MySQL». Він став дефолтним, бо виживає у реальних навантаженнях: відновлення після збою, блокування на рівні рядка та транзакції.
  • Факт 3: Старий модель розміру redo-журналу (розмір файлу × кількість файлів у групі) — причина, чому його зміна раніше вимагала видалення/перейменування ib_logfile і рестарту. MySQL 8 покращив це управління ємністю redo-журналу.
  • Факт 4: innodb_flush_log_at_trx_commit за замовчуванням дорівнює 1 не випадково: це налаштування для надійності. Тиск на продуктивність не змінив фізики; він лише підштовхнув людей до спокуси хитрувати.
  • Факт 5: Таблиці WooCommerce з часом зростали (order items, meta-таблиці, аналітика). Патерн мета-таблиць гнучкий, але карає за погані індекси та інтенсивні записи.
  • Факт 6: Історично WordPress колись за замовчуванням використовував MyISAM. Багато міфів «WordPress повільний» походять з тієї епохи; сучасні вузькі місця інші й тонші.
  • Факт 7: MariaDB запровадила Aria як заміну MyISAM, але WooCommerce не повинен змішувати рушії для транзакційних записів замовлень, якщо ви любите загадкові баги.
  • Факт 8: «Query cache» колись була фішкою MySQL, на яку спиралися люди. У MySQL 8 її вже немає, бо вона спричиняла контенцію. Якщо хтось каже «увімкніть query cache», ви чуєте привида минулого.

Швидкий алгоритм діагностики (перший/другий/третій)

Ось як знайти вузьке місце без триденного суперечення з постачальником плагіна.

Перший: підтвердьте, що це очікування БД, а не PHP чи мережа

  • Виміряйте TTFB на балансувальнику навантаження / реверс-проксі і порівняйте з upstream часом відповіді.
  • Перевірте насиченість PHP-FPM (активні процеси, slowlog).
  • Якщо upstream повільний, а PHP не завантажений — підозрюйте очікування БД.

Другий: визначте, чи ви обмежені I/O, блокуваннями чи CPU

  • I/O-обмеженість: висока латентність fsync, скидання брудних сторінок, очікування InnoDB.
  • Обмеженість блокуваннями: час очікування блокувань, багато потоків у черзі, «гарячі» рядки/таблиці (часто wp_options або order meta).
  • CPU-обмеженість: високе навантаження CPU, важкі запити, погані індекси, великі сортування/тимчасові таблиці.

Третій: виправте одну річ, яка прибирає чергу

  • Якщо I/O-обмеженість і redo-журнал малий: збільште ємність redo-журналу (реальний фікс).
  • Якщо блокування: зменшіть контенцію (індекси, обсяг транзакцій, поведінка плагінів).
  • Якщо CPU: оптимізуйте запити, індекси та буферний пул; зупиніть запит, що робить повний скан таблиці під час оформлення.

Тільки потім — і тільки потім — розглядайте компроміси надійності чи зміну рушія.

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

Все нижче призначене для запуску на типовому Linux-хості з MySQL/MariaDB. Замініть сокет/облікові дані за потребою. Кожне завдання містить: команду, приклад виводу, що це означає і яке рішення прийняти.

Завдання 1: Підтвердьте версію сервера та вендора (не гадати)

cr0x@server:~$ mysql --version
mysql  Ver 8.0.36 for Linux on x86_64 (MySQL Community Server - GPL)

Значення: Ви на MySQL 8.0. Налаштування redo-журналу використовує innodb_redo_log_capacity.

Рішення: Не слідуйте порадами специфічним для MariaDB без перевірки еквівалентів.

Завдання 2: Перевірте активні налаштування надійності (виявити «маскування»)

cr0x@server:~$ mysql -Nse "SHOW VARIABLES WHERE Variable_name IN ('innodb_flush_log_at_trx_commit','sync_binlog');"
innodb_flush_log_at_trx_commit	1
sync_binlog	1

Значення: Повністю надійні значення за замовчуванням. Добре для грошових операцій. Також це означає, що витрати на fsync реальні і їх треба вирішувати правильним I/O та розмірами redo.

Рішення: Тримайте це на 1, якщо у вас немає письмового прийняття ризиків та протестованої поведінки при збоях.

Завдання 3: Виміряйте тиск на з’єднання та конкуренцію

cr0x@server:~$ mysql -Nse "SHOW GLOBAL STATUS LIKE 'Threads_running'; SHOW GLOBAL STATUS LIKE 'Threads_connected';"
Threads_running	18
Threads_connected	120

Значення: 18 активних потоків — не катастрофа, але 120 підключених вказує на рух з’єднань або високу веб-конкуренцію.

Рішення: Якщо Threads_running стрибає під час сплесків оформлення, співвіднесіть із часом очікування блокувань та I/O.

Завдання 4: Перевірте розмір буферного пулу InnoDB (читання з RAM?)

cr0x@server:~$ mysql -Nse "SHOW VARIABLES LIKE 'innodb_buffer_pool_size';"
innodb_buffer_pool_size	4294967296

Значення: 4 GiB буферного пулу. Для магазину з істотним трафіком і великими meta-таблицями це може бути замало.

Рішення: Якщо на хості є вільна ОЗП, орієнтуйтесь на 60–75% від системної пам’яті для виділених DB-хостів (менше на шаред-хостах).

Завдання 5: Перевірте ємність / розмір redo-журналу (важіль «фіксу»)

cr0x@server:~$ mysql -Nse "SHOW VARIABLES LIKE 'innodb_redo_log_capacity';"
innodb_redo_log_capacity	104857600

Значення: 100 MiB ємності redo. Для сплесків транзакцій це часто комічно мало.

Рішення: Збільшіть до розумного значення (часто 1–4 GiB залежно від швидкості записів і толерантності відновлення). Перевірте вільне місце на диску й очікуваний час відновлення.

Завдання 6: Спостерігайте тиск на контрольні точки та скидання

cr0x@server:~$ mysql -e "SHOW ENGINE INNODB STATUS\G" | sed -n '1,120p'
*************************** 1. row ***************************
  Type: InnoDB
  Name:
Status:
=====================================
2025-12-29 09:17:21 0x7f3b3c0  INNODB MONITOR OUTPUT
=====================================
...
Log sequence number          112233445566
Log flushed up to            112233440000
Pages flushed up to          112233000000
Last checkpoint at           112232900000
...
Modified db pages            84210
...
Pending flushes (fsync) log: 0; buffer pool: 37

Значення: Багато змінених сторінок і відкладених скидань буферного пулу вказують, що фоновий flusher зайнятий. Якщо це стрибає під час оформлення, ви I/O/redo-обмежені.

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

Завдання 7: Перевірте очікування блокувань і дедлоки під час сплесків оформлення

cr0x@server:~$ mysql -Nse "SHOW GLOBAL STATUS LIKE 'Innodb_row_lock_time'; SHOW GLOBAL STATUS LIKE 'Innodb_row_lock_waits';"
Innodb_row_lock_time	98342
Innodb_row_lock_waits	217

Значення: Є очікування блокувань. Не обов’язково катастрофа, але якщо це стрибає під час оформлення — у вас контенція.

Рішення: Виявте «гарячі» таблиці/запити (наступні завдання). Якщо очікування пов’язані з оновленнями autoload у wp_options або оновленнями запасів — виправте індекси та обсяг транзакцій.

Завдання 8: Знайдіть топ повільних запитів (використовуйте slow log, а не інтуїцію)

cr0x@server:~$ mysql -Nse "SHOW VARIABLES LIKE 'slow_query_log'; SHOW VARIABLES LIKE 'long_query_time';"
slow_query_log	ON
long_query_time	1.000000

Значення: Slow query log увімкнений, поріг 1с. Добре — проблеми оформлення часто ховають кілька запитів на 2–5с.

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

Завдання 9: Перевірте латентність диска та підтвердіть реальність fsync

cr0x@server:~$ iostat -x 1 3
Linux 6.5.0 (server) 	12/29/2025 	_x86_64_	(8 CPU)

avg-cpu:  %user   %nice %system %iowait  %steal   %idle
          12.50    0.00    6.25   18.75    0.00   62.50

Device            r/s     w/s   rkB/s   wkB/s  await  svctm  %util
nvme0n1         45.0   220.0  2200.0  9800.0   9.80   0.35  85.00

Значення: await ~10ms з високою завантаженістю і iowait ~19%. Для навантаженої транзакційної БД 10ms уже може бути болісно. Якщо під час сплесків оформлення це зростає — ви відчуватимете це.

Рішення: Якщо await висока: виправте сховище (NVMe, політика кешування RAID-контролера, файлову систему, «шумних сусідів») перш ніж звинувачувати SQL-рушій.

Завдання 10: Перевірте розростання таблиць і відсутні індекси в точках навантаження WooCommerce

cr0x@server:~$ mysql -e "SELECT table_name, engine, table_rows, round((data_length+index_length)/1024/1024,1) AS MB FROM information_schema.tables WHERE table_schema=DATABASE() AND table_name IN ('wp_postmeta','wp_options','wp_woocommerce_order_items','wp_woocommerce_order_itemmeta') ORDER BY MB DESC;"
+------------------------------+--------+------------+--------+
| table_name                   | engine | table_rows | MB     |
+------------------------------+--------+------------+--------+
| wp_postmeta                  | InnoDB |    8200000 | 2150.4 |
| wp_options                   | InnoDB |      98000 |  210.7 |
| wp_woocommerce_order_itemmeta| InnoDB |    2400000 |  640.9 |
| wp_woocommerce_order_items   | InnoDB |     310000 |   96.2 |
+------------------------------+--------+------------+--------+

Значення: Великі meta-таблиці. Це нормально. Питання — чи запити до них індексовані і чи wp_options не має autoload-надлишку.

Рішення: Плануйте перегляд індексів і очищення опцій. Великі таблиці — не злочин; незіндексований доступ — проблема.

Завдання 11: Виявити autoload-надлишок (тихий вбивця оформлення)

cr0x@server:~$ mysql -e "SELECT ROUND(SUM(LENGTH(option_value))/1024/1024,2) AS autoload_mb FROM wp_options WHERE autoload='yes';"
+-------------+
| autoload_mb |
+-------------+
|       18.74 |
+-------------+

Значення: ~19 MiB автозавантаження на кожен запит. Це важко; збільшує перемішування пам’яті та час запитів, і може підсилювати контенцію, якщо опції часто оновлюються.

Рішення: Зменшіть autoload. Виявляйте винуватців; виносьте трансієнти з autoload; аудитуйте плагіни, що скидають великі масиви в options.

Завдання 12: Знайти, які опції створюють проблему

cr0x@server:~$ mysql -e "SELECT option_name, ROUND(LENGTH(option_value)/1024,1) AS kb FROM wp_options WHERE autoload='yes' ORDER BY LENGTH(option_value) DESC LIMIT 10;"
+---------------------------+--------+
| option_name               | kb     |
+---------------------------+--------+
| plugin_x_cache_blob       | 2048.0 |
| woocommerce_sessions      | 1536.0 |
| theme_builder_settings    |  980.4 |
| plugin_y_rules            |  620.7 |
| rewrite_rules             |  410.2 |
| cron                      |  350.1 |
| widget_text               |  290.5 |
| wp_user_roles             |  210.3 |
| plugin_z_feed_state       |  185.9 |
| woocommerce_tax_rates     |  160.4 |
+---------------------------+--------+

Значення: Деякі плагіни зберігають мегабайти в autoload. Це не «WordPress»; це використання таблиці options як смітника.

Рішення: Змініть autoload на ‘no’ там, де безпечно, або налаштуйте плагіни. Валідируйте у staging.

Завдання 13: Перевірити формат бінлогу та надійність для транзакційної безпеки

cr0x@server:~$ mysql -Nse "SHOW VARIABLES WHERE Variable_name IN ('log_bin','binlog_format','sync_binlog');"
log_bin	ON
binlog_format	ROW
sync_binlog	1

Значення: Реплікація дружня й надійна. Binlog у форматі ROW зменшує сюрпризи при складних записах.

Рішення: Якщо хтось пропонує sync_binlog=0 щоб «поправити оформлення», спитайте про їхній план відновлення, коли бінлог не міститиме «оплачених» замовлень.

Завдання 14: Визначити топ очікувань (performance schema MySQL 8)

cr0x@server:~$ mysql -e "SELECT event_name, COUNT_STAR, ROUND(SUM_TIMER_WAIT/1000000000000,2) AS seconds_waited FROM performance_schema.events_waits_summary_global_by_event_name WHERE event_name LIKE 'wait/io/file/innodb/%' ORDER BY SUM_TIMER_WAIT DESC LIMIT 8;"
+------------------------------------------+------------+----------------+
| event_name                               | COUNT_STAR | seconds_waited |
+------------------------------------------+------------+----------------+
| wait/io/file/innodb/innodb_redo          |   18422091 |          812.34|
| wait/io/file/innodb/innodb_data_file     |    3922011 |          244.12|
| wait/io/file/innodb/innodb_log_file      |    1200099 |          120.44|
| wait/io/file/innodb/innodb_temp_file     |      22011 |           11.02|
+------------------------------------------+------------+----------------+

Значення: Очікування на redo домінують. Це яскрава стрілка у напрямку розміру redo і латентності диска.

Рішення: Збільшіть ємність redo і перевірте знову. Якщо очікування redo залишаються — наступний підозрюваний — сховище/fsync.

Завдання 15: Захопіть реальний вигляд в реальному часі під час тесту оформлення

cr0x@server:~$ mysqladmin -i 1 -c 5 processlist status
Uptime: 123456  Threads: 125  Questions: 9933221  Slow queries: 18  Opens: 322  Flush tables: 1  Open tables: 256  Queries per second avg: 80.50
Id: 31142  User: wp   Host: 10.0.2.15:43218  db: shop  Command: Query  Time: 3  State: Waiting for handler commit  Info: UPDATE wp_postmeta SET meta_value='...'
Id: 31151  User: wp   Host: 10.0.2.15:43222  db: shop  Command: Query  Time: 3  State: Waiting for handler commit  Info: INSERT INTO wp_posts ...
Uptime: 123457  Threads: 128  Questions: 9933310  Slow queries: 18  Opens: 322  Flush tables: 1  Open tables: 256  Queries per second avg: 92.10

Значення: «Waiting for handler commit» — класичний знак тиску на commit/fsync (не завжди, але часто). Якщо запити оформлення зависають тут — ви платите за латентність сховища в момент commit.

Рішення: Не заклеюйте кешами. Вирішіть шлях запису: ємність redo, латентність сховища та поведінку скидання.

Три корпоративні міні-історії з фронту оформлення

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

Середній рітейлер мігрував стек WooCommerce з MySQL на MariaDB, бо «це drop-in заміна і швидше». План міграції на папері був чистий: дамп, імпорт, переключити кінцеві точки — готово. Вони зробили швидкий тест перегляду, зробили кілька замовлень у staging і вивели на прод у тихий вівторок.

Оформлення було нормальним день. Потім вийшла маркетингова розсилка і сайт отримав знайому форму трафіку: багато переглядів, а потім різкий сплеск оформлень за 10–15 хвилин. Замовлення почали таймаутитися, але авторизації платежів проходили. Приходили звернення підтримки: «Мене стягнули, але підтвердження немає». Ви вже знаєте продовження.

Хибне припущення не було «MariaDB погана». Воно полягало в думці «заміна рушія вирішить латентність». Реальна проблема була в латентності сховища при fsync і занадто малому redo-журналі. Новий БД поводився достатньо інакше, щоб здаватися новою проблемою, але фізика була тією самою. Вони просто постійно робили контрольні точки під тиском.

Їм вдалося стабілізувати систему, збільшивши розмір redo-журналу й налаштувавши I/O capacity під пристрій. Потім вони закрили операційний проріх: навантажувальні тести, що включають сплески оформлення, а не лише хіти головної сторінки. Тиждень був неприємний, але магазин перестав списувати гроші в порожнечу.

Міні-історія 2: Оптимізація, що зіграла злий жарт

Агенція SaaS, що запускала кілька магазинів WooCommerce на вузлі, мала постійну скаргу: «оформлення повільне у пікові години». Хтось помітив, що innodb_flush_log_at_trx_commit було встановлено в 1 і вирішив, що це «надто суворо». Вони змінили його на 2 по всьому флоту під час вікна технічного обслуговування. Затримка одразу зменшилася. Радість у команді була велика.

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

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

Виправлення не було «ніколи не налаштовувати надійність». Виправлення — перестати використовувати ослаблення надійності як опору продуктивності. Вони повернули 1, збільшили ємність redo-журналу і перевели найгірші магазини на краще сховище. Оформлення залишилося достатньо швидким, і «зниклі оплачені замовлення» перестали бути проблемою.

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

Команда enterprise запускала WooCommerce як «допоміжний бізнес» на платформі, що спільно використовувалась з іншими додатками. Нічого особливого — саме це і добре. Керівник SRE наполягав на двох нудних практиках: тримати увімкненим slow query log (з адекватною ротацією) і щотижня робити «топ-10 запитів». Ніяких геройств, лише гігієна.

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

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

Оформлення відновилося за годину. Ніякої зміни БД, ніяких хитрощів по надійності, ніякого додавання серверів. Просто похмура компетентність: мати дані, коли вони потрібні.

Поширені помилки: симптом → корінь → виправлення

1) Симптом: p95 оформлення стрибає під час сплесків; CPU низький

Корінь: Примусове checkpointing InnoDB через крихітні redo-журнали; тиск на скидання створює затримки.

Виправлення: Збільшити innodb_redo_log_capacity (MySQL 8) або innodb_log_file_size (MariaDB/старі MySQL). Перевірити латентність сховища за допомогою iostat.

2) Симптом: «Waiting for handler commit» домінує в processlist

Корінь: Латентність commit/fsync (погане сховище, насичений диск або занадто багато дрібних commit-ів).

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

3) Симптом: Таймаути очікування блокувань навколо оформлення

Корінь: Гарячі рядки/таблиці (рядки запасів, options, таблиці сесій), довгі транзакції, відсутні індекси.

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

4) Симптом: Заміна MySQL ↔ MariaDB «допомагає», але не вирішує

Корінь: Заміна рушія змінила поведінку за замовчуванням, але не вирішила основні проблеми I/O і схеми.

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

5) Симптом: Оформлення повільніше лише після встановлення «продуктивного» плагіна

Корінь: Плагін додає синхронне логування, надмірні autoload опції або виконує важкі запити на хук оформлення.

Виправлення: Відключити плагін для підтвердження; зробити логування асинхронним; очистити autoload; профілювати запити під час оформлення.

6) Симптом: Репліка відстає, коли зростають оформлення

Корінь: Первинний вузол I/O-обмежений; настройки flush binlog; репліка повільно застосовує великі транзакції.

Виправлення: Виправте шлях запису на primary; перевірте sync_binlog=1; переконайтесь, що сховище репліки порівнянне; моніторте apply lag.

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

Покроково: виправити затримки оформлення, не граючи з втратою даних

  1. Базова латентність: зафіксуйте p50/p95 для endpoint оформлення та індикатори часу commit БД.
  2. Підтвердьте рушій/версію: MySQL 8 vs MariaDB змінює “регулі” та дашборди.
  3. Виміряйте латентність сховища: запустіть iostat -x під контрольованим сплеском оформлення.
  4. Перевірте розмір redo: якщо redo <1 GiB на реальному магазині — вважайте його недостатнім, поки не доведено протилежне.
  5. Безпечно збільшіть ємність redo: MySQL 8 робить це легше; плануйте вікно для MariaDB/старих версій.
  6. Тримайте надійність: залишайте innodb_flush_log_at_trx_commit=1, якщо у вас немає письмового та протестованого ризик-моделювання.
  7. Перевірте буферний пул: переконайтесь, що гарячий робочий набір поміщається; уникайте свапінгу.
  8. Знайдіть «гарячі» блокування: використайте стан InnoDB, lock waits і processlist під час оформлення.
  9. Очистіть autoload: зменшення автозавантаження — низьковисока робота з великим ефектом.
  10. Проіндексуйте те, що читає оформлення: особливо postmeta і order meta патерни, які використовують плагіни.
  11. Перевірте під сплеском: не тестуйте одним замовленням; тестуйте 20–50 оформлень у короткому вікні.
  12. Впроваджуйте обережно: один магазин/вузол за раз, дивіться метрики, потім масштаб.

Коли обрати MySQL або MariaDB для WooCommerce

  • Обирайте MySQL 8, якщо вам потрібна потужна вбудована інструментація, сучасне управління redo та широка сумісність у керованих платформах.
  • Обирайте MariaDB, якщо ваша платформа стандартизована на ній, ви виграєте від її thread pool/функцій конкуренції і команда добре знає її особливості.
  • Уникайте перемикання як «фіксу продуктивності», якщо ви не можете назвати точний механізм, який очікуєте покращити (і як вимірюватимете зміни).

Жарт №2: «Просто перемкнемо базу даних» — це доросла версія вимкнення монітора і увімкнення його назад, бо таблиця виглядає неправильно.

Один вислів, який варто «татуювати» в runbook (вголос)

Парафразована думка від John Allspaw: надійність — це фіча, і ви не отримуєте її випадково.

Питання й відповіді

1) Чи MariaDB швидша за MySQL для WooCommerce?

Іноді, в певних сценаріях конкуренції. Але затримки оформлення частіше пов’язані з I/O і тиском redo/checkpoint, а не з сирою швидкістю запитів. Обирайте за операційною придатністю та спостережуваністю, а не за фольклором.

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

Збільшення ємності/розміру redo-журналу, щоб InnoDB припинив робити контрольні точки до втрати темпу під час сплесків записів. Потім перевірка латентності сховища.

3) Чому не просто встановити innodb_flush_log_at_trx_commit=2?

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

4) Яким має бути розмір redo-журналів?

Один універсальний номер відсутній. Для багатьох магазинів WooCommerce з реальним трафіком 1–4 GiB є поширеним початковим діапазоном. Балансуєте: менше затримок проти довшого відновлення після збою. Міряйте до і після.

5) Якщо CPU низький, чому оформлення повільне?

Тому що база може чекати I/O (fsync, запис у data files) або блокувань. CPU-графіки погано показують очікування; дивіться performance schema і метрики I/O.

6) Чи можуть автозавантажені опції реально впливати на оформлення?

Так. Autoload-надлишок збільшує роботу на запит, перемішування пам’яті і може створювати контенцію, якщо опції часто оновлюються. Класичний патерн «смерть зручністю».

7) Чи ставити таблиці WooCommerce на MyISAM/Aria заради швидкості?

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

8) Чи потрібен query cache, щоб прискорити WooCommerce?

Ні. MySQL 8 його прибрав. Використовуйте належні індекси, розмір буферного пулу і кешування на рівні додатка там, де це має сенс (але не для оформлення).

9) Що робити, якщо збільшення ємності redo не допомогло?

Тоді вузьке місце швидше за все — латентність сховища, контенція блокувань або конкретний повільний шлях запитів під час оформлення (часто спричинений плагінами). Використайте підсумки очікувань і slow-логи, щоб точково виявити проблему.

10) Чи переходити на керовану базу даних?

Якщо ваша поточна проблема — «ми не вміємо операційно керувати сховищем і бекапами», то так — керований сервіс усуне багато режимів відмов. Але він не виправить погану схему або поведінку плагінів автоматично.

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

  1. Запустіть перевірки версії та налаштувань надійності. Переконайтесь, що ви не вже «маскуєте» проблему.
  2. Виміряйте латентність диска під невеликим сплеском тестових оформлень. Якщо await некрасивий — виправте сховище першочергово.
  3. Перевірте ємність/розмір redo. Якщо вона крихітна — збільшіть обережно і відслідкуйте тиск контрольних точок.
  4. Виміряйте очікування блокувань і перегляньте autoload-надлишок у wp_options. Почистіть головних винуватців.
  5. Увімкніть/підтвердіть slow query logging і зафіксуйте вікно оформлення. Виправляйте те, що реально повільне, а не те, що модно.

Якщо зробити лише одне: припиніть трактувати налаштування надійності як тюнінг продуктивності. Задайте розмір redo-журналів, перевірте диск і зробіть оформлення знову нудним.

← Попередня
Рулетка оновлення BIOS: найвідважніше натискання в ІТ
Наступна →
Підтримка зменшення руху: prefers-reduced-motion виконано правильно

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