База WordPress роздута: безпечне очищення autoload у wp_options без збоїв

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

Коли WordPress стає «таємниче повільним», винуватцем часто буває не PHP, не тема й навіть не ваш сервер бази даних. Це шаблон одного рядка таблиці: wp_options, набитий мегабайтами автозавантажуваного сміття, яке WordPress сумлінно тягне в пам’ять на кожен запит.

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

Зміст

Що насправді означає autoload (і чому це шкодить)

wp_options — це «скринька на все» у WordPress. Налаштування, стан плагінів, кеші, фічеві прапорці, API-токени, розклади cron і «тимчасові» значення, що живуть вічно — більшість з них потрапляє сюди.

Ключове поле: autoload. Якщо опція має autoload='yes', WordPress намагається завантажити її рано (через wp_load_alloptions()), щоб обслуговувати запити без великої кількості дрібних запитів. Це добра ідея, коли автозавантажувані дані малі й стабільні. Це погана ідея, коли вони займають 10–100+ МБ серіалізованих масивів, конфігів віджетів, величезних кешів плагінів та маркетингових плагінів, які ніколи не відмовляються від зайвого спільного доступу до бази.

Ось режим відмови: автозавантажувані опції підтягуються на більшості запитів (фронтенд і адмін). Навіть якщо у вас є object cache, ці значення все одно треба раз за цикл кеша завантажити в пам’ять і часто копіювати/серіалізувати. Чим більше вони, тим більше ви спалюєте CPU і пам’яті, і тим сильніше підвищується затримка під час пропусків кеша, деплоїв, перезапусків контейнерів або перемикань відмови.

Суха правда: ви не «оптимізуєте MySQL» від цього. Ви припиняєте автозавантажувати сміття.

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

Autoload — це не «кеш»

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

Чому це вражає продуктивність дивними, сплескоподібними способами

  • Холодні старти: перезапуски FPM, пересів контейнера, масштабування нових інстансів — автозавантажувані опції треба «погріти». Саме тоді сайт сповільнюється найбільше.
  • Крутіж об’єктного кеша: якщо ваш object cache часто викидає дані, ви перезавантажуєте autoload частіше, ніж думаєте.
  • Затримка реплікації: оновлення великих опцій спричиняють більші binlog/зміни рядків, що збільшує лаг під навантаженням.
  • Блокування/IO: оновлення великих опцій — це великі записи, і на спільному сховищі або при перевантажених дисках ви платите затримкою.

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

Якщо сайт на WordPress повільний і ви підозрюєте autoload у wp_options, не блукайте. Перевірте три речі у такому порядку:

1) Чи великі автозавантажувані дані?

Запустіть швидку суму розмірів автозавантажуваних опцій. Якщо вона понад кілька МБ — у вас підозра. Якщо десятки МБ — у вас винуватець.

2) Які опції завдають шкоди?

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

3) Чи пов’язана повільність із пропусками кеша/перезапусками?

Корелюйте сплески з перезапусками FPM, пересівами контейнерів або викидами Redis/Memcached. Autoload-блок підсилює біль холодних стартів.

Потім вирішіть: видалити очевидне сміття (прострочені transient, залишки плагінів) і перевести «велике, але потрібне іноді» з автозавантаження в неавтозавантажуване, ідеально замінивши його на правильний кеш.

Цікаві факти та історія, які можна використати

  1. Опції WordPress передували багатьом сучасним плагінам: API опцій був спроектований для невеликих налаштувань, а не для мегабайтних блобів.
  2. Autoload задумували щоб зменшити кількість запитів: у ранні часи багато дрібних запитів були більшим злом, ніж зайва пам’ять.
  3. Серіалізовані PHP-масиви дозволяли зберігати будь-що: це також зробило легким зберегти все й назавжди, без тиску схеми.
  4. Transients були введені як «тимчасовий кеш»: але без постійного object cache вони часто живуть у wp_options і накопичуються.
  5. Багато плагінів використовують wp_options як смітник: бо він універсально доступний, а не тому що це доречно.
  6. WooCommerce часто страждає: не тому, що WooCommerce унікально поганий, а тому що велика кількість плагінів підвищує зміну опцій.
  7. Autoload-блок може ховатися за CDN: сторінки здаються «швидкими» з кешу, поки кеш не спаде або авторизований користувач не потрапить на динамічні кінцеві точки.
  8. Розмір бази даних — не головний метрик: база 2 ГБ може бути нормальною; а автозавантажувальний payload 20 МБ на кожен запит — ні.
  9. Деякі хости «оптимізують» запуском OPTIMIZE TABLE: що не виправляє autoload-блок і може додати IO/блокування, якщо робити це невчасно.

Спочатку виміряйте: як виглядає «роздування» в числах

Робота в продакшені починається з вимірювань. Не з відчуттів. Мета — відповісти на питання:

  • Який розмір автозавантажуваного payload?
  • Хто головні винуватці?
  • Чи зростає це?
  • Що безпечно видаляти, а що краще деавтолюдити?

Правила великого пальця (суб’єктивно, бо вас попросили):

  • < 1 МБ автозавантаження загалом: ймовірно, нормально. Не створюйте зайвої роботи.
  • 1–5 МБ: слідкуйте; дослідіть кілька топових елементів.
  • 5–20 МБ: ви платите податок затримки. Чистіть.
  • > 20 МБ: ви в зоні інцидентів; холодні старти будуть некрасивими.

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

І ще одна мантра з практики надійності: Усе постійно ламається. — Вернер Фогельс (парафраз). Autoload-блок перетворює рутинні відмови (перезапуски, викиди) у помітну для користувача повільність.

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

Ці завдання написані для операторів. Вони включають команду, приклад виводу, що це означає і яке рішення прийняти. Припустимо, у вас є shell-доступ і WP-CLI або клієнт MySQL. Налаштуйте імена БД/префікси таблиць за потреби.

Task 1: Confirm table prefix and DB credentials (don’t guess)

cr0x@server:~$ cd /var/www/html && wp config get table_prefix
wp_

Що це означає: Ваш префікс таблиць — wp_. Якщо ви припускали wp_, а насправді префікс wpx9_, кожен SQL-запит буде неправильним або небезпечним.

Рішення: Використовуйте повернений префікс у всіх наступних запитах. Якщо WP-CLI не може прочитати конфіг, зупиніться і виправте доступ спершу.

Task 2: Find autoload payload size (quick and decisive)

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

Що це означає: ~29 МБ завантажується як «alloptions». Це не «трохи повільно». Це повторюваний податок на кожен холодний запит.

Рішення: Ідентифікуйте головних винуватців; плануйте контрольоване вікно для очищення.

Task 3: Identify top autoloaded options by size

cr0x@server:~$ wp db query "SELECT option_name, ROUND(LENGTH(option_value)/1024/1024,2) AS mb FROM wp_options WHERE autoload='yes' ORDER BY LENGTH(option_value) DESC LIMIT 20;"
+------------------------------+------+
| option_name                  | mb   |
+------------------------------+------+
| plugin_x_cache_blob          | 12.40|
| widget_custom_html           | 4.12 |
| rewrite_rules                | 2.33 |
| some_builder_global_settings | 1.98 |
| cron                         | 1.21 |
+------------------------------+------+

Що це означає: Одна чи дві опції домінують. Це добра новина: ви можете отримати великий виграш, не граючи у whack-a-mole.

Рішення: Для кожного топ-винуватця вирішіть: видалити, зняти autoload або лишити. Почніть з очевидних кеш-блобів і залишків плагінів.

Task 4: Check if a suspicious option is a transient (usually safe to purge)

cr0x@server:~$ wp db query "SELECT option_name, autoload FROM wp_options WHERE option_name LIKE '\_transient\_%' LIMIT 5;"
+------------------------------+----------+
| option_name                  | autoload |
+------------------------------+----------+
| _transient_timeout_feed_123  | no       |
| _transient_feed_123          | no       |
| _transient_timeout_xxx       | no       |
| _transient_xxx               | no       |
| _transient_timeout_abc       | no       |
+------------------------------+----------+

Що це означає: Більшість transient не автозавантажуються, але вони все одно роздувають таблицю й уповільнюють сканування/бекапи. Деякі плагіни помилково автозавантажують transient або зберігають «transient-подібні» дані без префіксу.

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

Task 5: Count expired transients (cheap win)

cr0x@server:~$ wp db query "SELECT COUNT(*) AS expired FROM wp_options WHERE option_name LIKE '\_transient\_timeout\_%' AND option_value < UNIX_TIMESTAMP();"
+---------+
| expired |
+---------+
| 18742   |
+---------+

Що це означає: У вас багато прострочених transient. WordPress не завжди агресивно їх очищає, а плагіни можуть бути неакуратними.

Рішення: Видалити їх (і відповідні парні значення) контрольовано.

Task 6: Delete expired transients via WP-CLI (safe-ish and reversible by regeneration)

cr0x@server:~$ wp transient delete --expired
Success: Deleted 18742 expired transients.

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

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

Task 7: Re-measure autoload payload after transient cleanup

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

Що це означає: Transient не були головною причиною; основний обсяг все ще в автозавантажуваних опціях, як-от кеш-блоби.

Рішення: Цілитися безпосередньо в топ-винуватців.

Task 8: Snapshot the option value before changing it (you want rollback)

cr0x@server:~$ wp option get plugin_x_cache_blob --format=json | head -c 200
{"version":"4.2.1","generated_at":1735230932,"data":{"items":[{"id":1,"name":"..."}]}}

Що це означає: Видно, що це згенерована кеш-структура, а не ядрове налаштування. Це пахне тим, що це можна перемістити з автозавантаження.

Рішення: Збережіть повне значення у файл (або зробіть бекап БД) перед змінами. Потім розгляньте спочатку відключення autoload, а не видалення.

Task 9: Disable autoload for a known cache blob (minimal functional risk)

cr0x@server:~$ wp db query "UPDATE wp_options SET autoload='no' WHERE option_name='plugin_x_cache_blob' LIMIT 1;"
Query OK, 1 row affected (0.02 sec)
Rows matched: 1  Changed: 1  Warnings: 0

Що це означає: Ця опція все ще існує; WordPress більше не буде завантажувати її автоматично. Плагін підвантажуватиме її при потребі.

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

Task 10: Validate autoload payload after de-autoloading one big offender

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

Що це означає: Ви майже наполовину скоротили автозавантажувальний payload. Це зміна, яка відобразиться в p95 затримці.

Рішення: Продовжуйте обробляти топ-винуватців. Віддавайте перевагу autoload=no замість DELETE, якщо ви не впевнені.

Task 11: Find orphaned options from deactivated plugins (cleanup candidates)

cr0x@server:~$ wp plugin list --status=inactive
+----------------------+----------+-----------+---------+
| name                 | status   | update    | version |
+----------------------+----------+-----------+---------+
| old-gallery-plugin   | inactive | none      | 1.9.0   |
| legacy-seo-tool      | inactive | available | 2.3.1   |
+----------------------+----------+-----------+---------+

Що це означає: Неактивні плагіни часто лишають опції. Деякі нешкідливі. Деякі великі. Неактивний + великий + autoload=yes — це подарунок.

Рішення: Шукайте префікси опцій, пов’язані з неактивними плагінами, потім видаляйте ці опції після бекапу.

Task 12: Locate options by name pattern and size before deleting

cr0x@server:~$ wp db query "SELECT option_name, autoload, ROUND(LENGTH(option_value)/1024/1024,2) AS mb FROM wp_options WHERE option_name LIKE 'old_gallery_%' ORDER BY LENGTH(option_value) DESC LIMIT 10;"
+---------------------------+----------+------+
| option_name               | autoload | mb   |
+---------------------------+----------+------+
| old_gallery_cache         | yes      | 3.70 |
| old_gallery_settings      | yes      | 0.05 |
+---------------------------+----------+------+

Що це означає: Ймовірно це мертва вага, якщо плагін неактивний і ви не плануєте його повторно вмикати.

Рішення: Експортуйте рядки, потім видаліть. Якщо боїтесь — спочатку встановіть autoload=no і спостерігайте тиждень.

Task 13: Back up specific rows (surgical rollback)

cr0x@server:~$ wp db query "SELECT * FROM wp_options WHERE option_name IN ('old_gallery_cache','old_gallery_settings')\G"
*************************** 1. row ***************************
option_id: 8812
option_name: old_gallery_cache
option_value: a:3:{s:7:"version";s:5:"1.9.0";...}
autoload: yes
*************************** 2. row ***************************
option_id: 8813
option_name: old_gallery_settings
option_value: a:2:{s:5:"theme";s:6:"light";...}
autoload: yes

Що це означає: Ви зняли точні значення. Якщо видалення спричинить проблеми — ви можете вставити їх назад.

Рішення: Видаляйте тільки після збереження цього виводу або знімка БД.

Task 14: Delete known-orphan options (commit)

cr0x@server:~$ wp db query "DELETE FROM wp_options WHERE option_name IN ('old_gallery_cache','old_gallery_settings') LIMIT 2;"
Query OK, 2 rows affected (0.01 sec)

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

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

Task 15: Inspect rewrite_rules size (common, sometimes legitimate)

cr0x@server:~$ wp option get rewrite_rules --format=json | head -c 120
{"^wp-json/?$":"index.php?rest_route=/","^product/(.+?)/?$":"index.php?product=$matches[1]","^..."}

Що це означає: rewrite_rules зазвичай автозавантажується і може рости при складній маршрутизації (e-commerce, мультимовність тощо). Не вимикайте його бездумно; це може сповільнити маршрутизацію або спричинити дивну поведінку.

Рішення: Якщо воно величезне, ймовірно якийсь плагін генерує надмірні правила. Виправляйте джерело, а не лише симптом. Розгляньте безпечний flush rewrite rules під час технічних робіт.

Task 16: Flush rewrite rules (only when you know why)

cr0x@server:~$ wp rewrite flush --hard
Success: Rewrite rules flushed.

Що це означає: WordPress згенерував правила заново. Це може зменшити опцію, якщо накопичилися застарілі правила, але може й відтворити той самий розмір, якщо генератор все ще «шумить».

Рішення: Якщо стало менше — добре. Якщо повернулося — шукайте плагін/тему, яка додає надто багато маршрутів.

Task 17: Check whether object cache is enabled (it changes the blast radius)

cr0x@server:~$ wp plugin list --status=active | grep -E "redis|memcached|object"
redis-cache             active   none      2.5.3

Що це означає: Ймовірно вмикнуто persistent object caching. Це допомагає, але не виправдовує 30 МБ автозавантаження — особливо під час очищень і викидів кешу.

Рішення: Продовжуйте чистити. Також перевірте налаштування викиду кешу й розмір пам’яті, щоб зменшити churn.

Task 18: Measure request-level impact via a simple before/after TTFB sample

cr0x@server:~$ for i in {1..5}; do curl -s -o /dev/null -w "%{time_starttransfer}\n" https://example.com/; done
0.842
0.790
0.811
0.775
0.798

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

Рішення: Якщо TTFB знизився суттєво і тримається — ви підправили правильну річ. Якщо ні — вузьке місце в іншому: повільні запити, CPU, PHP, зовнішні API виклики.

Безпечні зміни: що можна видаляти, а що краще приборкати

Tier 1: Usually safe to delete (with backups)

  • Прострочені transients: Вони прострочені. Їх зазвичай не повинно бути необхідно відновлювати.
  • Сирітські опції плагінів: Для плагінів, які ви видалили або ніколи не збираєтеся вмикати знову.
  • Старі cron-lock-и: Якщо застрягли (підходьте обережно), але спершу підтвердьте, що сайт не виконує критичні задачі.

Навіть «безпечне» потребує бекапу. Видалення рядків — остаточне, і ви можете помилково видалити не ті префікси у втомі.

Tier 2: Prefer switching autoload from yes → no

  • Згенеровані кеші, що зберігаються як опції: Якщо вони великі, але плагін може їх згенерувати заново.
  • Великі UI-конфіги: Налаштування віджетів або будівельників, які не потрібні на кожному фронтенд-запиті.
  • Аналітичні або логоподібні блоби: Їм не місце в опціях, але переведення в autoload=no — безпечніший перший крок.

Чому це безпечніше? Бо дані залишаються. Ви змінюєте «коли завантажувати», а не «чи існує воно». Більшість плагінів просто викличе get_option() при потребі й продовжить працювати.

Tier 3: Don’t touch casually

  • siteurl, home, active_plugins: самоочевидно. Якщо ви їх зламаєте — отримаєте простій.
  • cron: великий — підозріло, але видалення може скинути заплановані задачі. Краще знайти, хто спамить cron.
  • rewrite_rules: автозавантажується не дарма; великий обсяг вказує на складність зверху.

Короткий жарт №2: Видалити active_plugins, щоб прискорити WordPress — це оптимізація продуктивності з побічним ефектом «немає сайту».

Справжня мета: зменшити «autoloaded hotset»

Думайте як інженер кешу. Autoload — це hotset: дані, які ви завантажуєте в пам’ять рано. Hotset має бути малим, стабільним і дійсно «гарячим». Усе інше має завантажуватися ліниво або кешуватися правильно (object cache, transient з TTL або окрема таблиця).

Три міні-історії з корпоративних боїв

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

Середній контент-бізнес запускав WordPress за reverse proxy і CDN. Сайт виглядав швидким у синтетичних перевірках, бо головна сторінка була завжди в кеші. Керівництво вирішило, що origin не має великого значення. «Лише адмін» повільний — цього не показували панелі.

Потім запустили фічу для членства. Авторизовані користувачі обходили більшість CDN-кешів, і origin став продуктом. У день запуску сайт не впав. Він просто перетворився на повільну катастрофу: сторінки профілю займали секунди; виклики для оформлення замовлення таймаутили; звернення в сапорт з’явилися швидше за пост-мортем.

Невірне припущення було тонким: «База нормальна, бо CPU низький». Насправді автозавантажувані опції розрослися в багатомегабайтний payload. Кожний новий PHP-воркер холодного старту мусив тягнути все це, і будь-який пропуск кеша вдаряв по БД великим запитом і важким десеріалізуванням.

Виправлення було нудним і ефективним: виміряли autoload, вимкнули autoload для найбільших кеш-опцій плагінів і видалили сирітські опції двох застарілих плагінів. Найбільше покращення було не в середній латентності; а в p95 і p99 під час сплесків і деплоїв. Вони перестали відчуватися як «випадкові», бо вже не були випадковими.

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

Маркетингова команда додала плагін, що обіцяв «зменшення кількості запитів до БД». Він знизив кількість запитів — шляхом агресивного кешування обчислених даних в одній опції і виставлення її на autoload. Автори плагіна, мабуть, тестували на маленьких сайтах і оголосили перемогу.

У продакшені опція росла з кожною кампанією та локалізацією. Payload надутів. Кількість запитів знизилася. Витрати пам’яті зросли. TTFB погіршився, особливо після очищень кешу після деплоїв.

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

Зрештою вони замінили підхід «кеш в опціях» на persistent object cache і встановили ту опцію як autoload=no. Кількість запитів трохи зросла. Латентність впала. Всі погодилися, що це й було планом спочатку.

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

Фінансова організація вела WordPress як контент-платформу поруч із транзакційними системами. Їхній найбільший страх — це інцидент, що відверне днювальну команду під час реального збою в іншій системі.

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

Через місяці оновлення плагіна додало нову автозавантажувану опцію, яка почала швидко зростати. Щотижневий тренд виявив це до того, як це стало помітним користувачам. Вони відкотили, відкрили тикет у вендора і зафіксували версію. Жодного інцидентного дзвінка. Жодних нічних героїв. Просто тиха корекція, про яку ніхто поза SRE не чув.

Ось у чому суть. Найкращий інцидент — той, який ніколи не відкриває Slack-канал.

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

1) Адмін повільний, фронтенд «здається нормальним»

Симптом: сторінки wp-admin зависають; редактори скаржаться; фронтенд виглядає нормально (дякуємо CDN).

Корінь: Autoload-блок карає некешований, авторизований трафік. Адмін-сторінки також завантажують більше плагінів і налаштувань.

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

2) Випадкові сплески затримки після деплоїв або масштабування

Симптом: одразу після деплою або перезапуску пода затримка підіймається, а потім спадає.

Корінь: холодні воркери + порожній object cache означають, що autoload payload треба частково або повністю витягти і десеріалізувати багаторазово.

Виправлення: Зменшіть autoload payload; забезпечте належний розмір persistent object cache; розгляньте скрипти «підгріву» після деплою, що б’ють по ключових кінцевих точках.

3) CPU БД низький, але запити «повільні»

Симптом: немає явного завантаження CPU БД; все одно повільно.

Корінь: Не весь біль — в CPU. Великі значення опцій означають більші пакети, більше копій в пам’яті і накладні витрати PHP при unserialize.

Виправлення: Зменшіть payload; проаналізуйте топ-винуватців; перевірте пам’ять/CPU PHP воркерів під час холодних запитів.

4) Ви видалили опцію і плагін «таємниче» зламався

Симптом: фіча зникла; налаштування скинуті; фатальні помилки.

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

Виправлення: Відновіть із бекапу; спочатку віддавайте перевагу autoload=no; видаляйте тільки відомі transient і підтверджені сирітські опції.

5) OPTIMIZE TABLE зробив гірше

Симптом: IO-сплески, реплікаційний лаг або уповільнення під час «обслуговування».

Корінь: OPTIMIZE не вирішує семантику autoload; воно може перебудувати таблиці і викликати важкий IO, особливо на великих наборах даних.

Виправлення: Не використовуйте OPTIMIZE як перший крок. Спочатку зменшіть autoload і сміттєві рядки. Плануйте обслуговування таблиць навмисно і рідко.

6) Розмір autoload впав, але продуктивність не покращилась

Симптом: ви скоротили autoload з 20 МБ до 5 МБ; користувачі все ще скаржаться.

Корінь: Вузьке місце в іншому: повільні зовнішні API, файловий диск, CPU PHP, відсутність індексів у postmeta або вичерпаний пул з’єднань БД.

Виправлення: Увімкніть slow query log; профілюйте PHP; перевірте затримки диска; перевірте здоров’я object cache; вимірюйте енд-ту-енд з реальним трафіком.

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

Фаза 0: Запобіжні заходи (зробіть перед зміною даних)

  • Підтвердьте префікс таблиць через WP-CLI (Task 1).
  • Зробіть знімок бази або дамп (повну БД якщо можливо; мінімум — wp_options).
  • Майте план відкату: відновлення дампа або вставка збережених рядків.
  • Визначте режим робіт: live-зміни з тісним моніторингом або коротке вікно техпідтримки.

Фаза 1: Базова оцінка і вибір цілей

  • Виміряйте autoload MB (Task 2).
  • Складіть список топ-20 автозавантажуваних опцій за розміром (Task 3).
  • Класифікуйте кожну опцію: видалити, деавтолюдити, лишити.
  • Запишіть очікуваний вплив і ризик для кожної зміни. Якщо не можете пояснити, що робить опція — не видаляйте її.

Фаза 2: Низькоризикове очищення (виграші, що майже ніколи не шкодять)

  • Видаліть прострочені transient (Tasks 5–6).
  • Приберіть сирітські опції від плагінів, які ви видалили (Tasks 11–14).
  • Після кожної партії змін повторно вимірюйте autoload MB і топ-винуватців.

Фаза 3: Високовпливове налаштування (де реальні виграші)

  • Для кожної великої неядрової опції: спочатку встановіть autoload=no (Task 9).
  • Тестуйте ключові шляхи відразу після кожної зміни (головна, вхід, оформлення замовлення, пошук, wp-admin).
  • Слідкуйте за PHP-логами помилок та логами застосунку на предмет попереджень/фаталів.
  • Видаляйте великі опції тільки коли впевнені, що їх можна згенерувати заново або вони справді сирітські.

Фаза 4: Правильна верифікація покращень

  • Виміряйте остаточний розмір autoload MB.
  • Зробіть до/після TTFB-заміри (Task 18) і порівняйте p95/p99 у вашому APM, якщо є.
  • Симулюйте холодний старт: перезапустіть PHP-FPM і очистіть object cache у стейджингу, потім протестуйте (не робіть це легковажно в проді).

Фаза 5: Забезпечте сталість

  • Додайте моніторинг розміру autoload і топ-винуватців.
  • Заблокуйте встановлення/оновлення плагінів перевіркою зростання autoload на стейджингу.
  • Освітіть команду: autoload — не сміттєсортувальна машина.

Профілактика: як не допустити повернення autoload-блоку

1) Ставтеся до встановлення плагінів як до змін коду

Якщо в організації є процес змін для коду, але немає для плагінів — вітаємо: ваші плагіни тепер нерев’юваний код. Багато найгірших autoload-винуватців походять від плагінів, які «кешують», запаковуючи масиви в опції.

Практична політика: кожне оновлення плагіна проходить прогрів на стейджингу, де ви фіксуєте autoload MB до і після типових робочих сценаріїв (збереження адмін-форм, імпорт продуктів, прогрів кешу). Якщо autoload росте суттєво — блокуйте або пом’якшуйте.

2) Віддавайте перевагу persistent object cache, але не ховайте гниль

Redis/Memcached зменшує повторювані хіти до БД. Це не робить нормальним автозавантаження 30 МБ. Воно лише змінює, коли ви платите.

Що вам потрібно: маленький автозавантажувальний hotset плюс кеш для обчислених даних зі здоровим TTL і поведінкою викиду.

3) Встановіть ліміти розмірів у операційному плейбуку

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

  • Попередження: autoload > 5 МБ
  • Зателефонувати комусь (у робочі години): autoload > 10–15 МБ
  • Критерій інциденту: autoload > 20 МБ плюс скорельовані сплески затримки

4) Питайте «чи має це бути в опціях?»

Деякі типи даних не повинні бути в опціях:

  • Логи (користуйтеся файлами, сервісом логування або кастомною таблицею)
  • Великі обчислені індекси (використовуйте transient з object cache або кастомні таблиці)
  • Стан на користувача/сесію (використовуйте user meta, сесії або спеціалізоване сховище)

5) Слідкуйте за зростанням cron і action scheduler

Опція cron може роздутися, якщо події накопичуються або плагін розписує забагато хуків. WooCommerce також має таблиці action scheduler (не wp_options), які можуть стати власним проектом очищення. Не плутайте їх; діагностуйте окремо.

FAQ

1) Яким має бути розмір автозавантажуваних опцій?

Ідеально — менше 1 МБ. Менше 5 МБ часто прийнятно. Понад 10 МБ зазвичай варто виправляти. Понад 20 МБ — ризик надійності під час холодних стартів.

2) Чи зламає сайт відключення autoload?

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

3) Чи безпечно видаляти transient?

Прострочені transient зазвичай безпечні для видалення. Непрострочені transient теж зазвичай безпечні (їх можна регенерувати), але деякі плагіни використовують їх як постійне сховище. Якщо хочете мінімальний ризик — видаляйте спочатку прострочені transient.

4) Чому rewrite_rules такий великий?

Складна маршрутизація (продукти, мови, кастомні типи постів) збільшує правила. Деякі плагіни генерують надмірні правила або не очищаються. Якщо воно величезне — дослідіть, що додає маршрути; flush rewrite rules може тимчасово допомогти, але вирішувати треба в генераторі.

5) Чи треба запускати OPTIMIZE TABLE після очищення?

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

6) У мене Redis object cache. Чому я все ще маю хвилюватись про autoload?

Бо кеші промахуються, перезапускаються, викидаються й очищуються. Autoload-блок робить ці нормальні події дорогими. Також великий autoload-пейлоад усе ще треба десеріалізувати і обробити в PHP.

7) Що, якщо найбільша автозавантажувана опція належить критичному плагіну?

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

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

Якщо це явно кеш (часто має в назві cache, transient-подібні префікси або містить часові мітки) і може бути регенеровано — видалення зазвичай безпечне. Якщо це конфігурація, ліцензійні ключі або ядрові налаштування — не видаляйте. Якщо сумніваєтеся: зробіть бекап і спочатку встановіть autoload=no.

9) Чи може autoload-блок спричинити помилки OOM у PHP?

Так. Великі автозавантажувані payload збільшують використання пам’яті на запит, особливо коли існує декілька копій під час unserialize/опрацювання. Якщо бачите OOM або фатальні помилки пам’яті PHP, корелюйте це з пропусками кеша — autoload може бути головним підозрюваним.

10) Як часто треба перевіряти wp_options?

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

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

Зробіть три речі в порядку:

  1. Виміряйте autoload MB (Task 2) і запишіть. Якщо ви цього не відстежуєте — не зупините регресії.
  2. Візьміть топ-винуватця (Task 3) і встановіть autoload=no (Task 9). Негайно протестуйте критичні потоки.
  3. Очистіть легке сміття: прострочені transient і сирітські опції плагінів (Tasks 5–6, 11–14).

Після цього ставте autoload як бюджет продуктивності. Тримайте його малим. Тримайте його нудним. Ваш майбутній я — найімовірніше той, хто чергуватиме о 2:00 — скаже вам дякую.

← Попередня
Сервери Ubuntu 24.04: Snap проти apt — коли Snap тихо створює проблеми (і що з цим робити)
Наступна →
WordPress 504 Gateway Timeout: база даних чи PHP? Як це довести

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