Це завжди відбувається в найбільш невдалий момент: ви натискаєте «Оновити» в адмінці, індикатор крутиться, а потім з’являється фатальна помилка про пам’ять. Або адмінка перетворюється на білу порожню сторінку, і ваш телефон починає дзвонити так, ніби ви навмисне видалили базу даних.
Цю проблему рідко вирішують сліпим «додаванням більше пам’яті». Вирішують розумінням того, яку пам’ять WordPress фактично може використовувати, що PHP реально споживає і що тихо «жере» ці ресурси: плагіни, обробка зображень, імпорти, cron-завдання та інколи тема, яка вважає рекурсію стилем життя.
Що насправді означає помилка (і чого вона не означає)
Класичне повідомлення виглядає так:
Фатальна помилка: вичерпано дозволений розмір пам’яті 268435456 байт (спробував виділити 20480 байт)
Перекладіть це як SRE:
- «Allowed memory size» — це ліміт пам’яті процесу PHP (
memory_limit), а не фізична оперативна пам’ять сервера. - Число в байтах каже вам ліміт на момент помилки (268 435 456 байт = 256M).
- «tried to allocate …» — це остання крапля, а не загальна відсутня кількість. Може бути не вистачало 20KB або 200MB. Ви ще не знаєте точно.
- Де це трапляється — важливо: запити в адмінці, WP-CLI, cron, AJAX, REST та обробка зображень можуть виконуватись під різними SAPI/пулами PHP з різними лімітами.
Чого це не означає:
- Це не обов’язково означає, що WordPress «потребує більше пам’яті». Іноді треба менше плагінів, менше автозавантажених опцій або менше гігантських масивів, створених з неправильно пагінованих запитів.
- Це не означає, що слід встановлювати
memory_limit = -1, якщо вам подобається перетворювати маленькі проблеми на великі інциденти. - Це не означає, що більше оперативної пам’яті сервера вирішить проблему. Ви можете мати 128GB RAM і все одно обмежити PHP до 128M, а потім дивуватися, чому WooCommerce помирає під час запиту.
Операційна істина така: WordPress — це PHP-додаток з екосистемою плагінів, яка може перевищити розумні межі, якщо ви не вимірюєте й не примусово контролюєте. Ваше завдання — зробити ліміт адекватним і зробити навантаження розумним.
Цікаві факти та трохи історії
Це не трюки для вікторини. Вони пояснюють, чому режими відмови такі поширені.
memory_limitу PHP існує з часів раннього PHP 4 як запобіжник від некерованих скриптів у шаред-хостингу. WordPress виріс у цьому середовищі.- «Біла сторінка смерті» у WordPress історично викликалась фатальними помилками PHP з вимкненим виводом. Вичерпання пам’яті — одна з топових причин.
- WordPress визначає дві константи пам’яті:
WP_MEMORY_LIMIT(фронтенд) іWP_MAX_MEMORY_LIMIT(адмін). Багато хто встановлює одну і вважає, що вистачить на обидва. - WooCommerce та конструктори сторінок змінили навантаження в адмінці: «адмінка» перестала бути кількома формами і стала SPA з важкими API-викликами та великими об’єктними графами.
- OPcache може зменшити churn пам’яті (менше перекомпіляцій), але сам споживає загальну пам’ять. Неправильне налаштування може спричинити дивні «воно іноді падає» симптоми.
- Обробка зображень стала важчою за роки через «responsive images» і множинні розміри за замовчуванням. Одне завантаження може означати багато ресайзів плюс парсинг EXIF.
- Composer autoloader та сучасні PHP-бібліотеки проникли в плагіни. Чудово для розробки, іноді катастрофічно для пам’яті, якщо вендори підключені кілька разів.
- Деякі хости запускають окремі PHP-FPM пули на сайт або на користувача. Це хороша ізоляція, але означає, що ваш «я змінив php.ini» патч часто влучає в інший пул.
- WP-Cron за замовчуванням — не справжній cron; він запускається тригером трафіку. Це означає, що важкі завдання можуть запуститися в найгірший момент: саме тоді, коли адміністратор оновлює плагіни.
Швидкий план діагностики
Якщо ви хочете швидко зупинити кровотечу, вам потрібен детермінований порядок перевірок. Не починайте з редагування трьох конфігів в надії. Робіть так:
1) Підтвердьте, де виконується запит і яку конфігурацію PHP він використовує
- Якщо це відбувається в wp-admin, ймовірно ви потрапляєте на PHP-FPM через Nginx/Apache proxy або на mod_php у Apache.
- Якщо це відбувається в WP-CLI, ви використовуєте CLI PHP (інший ini, інший memory_limit).
- Якщо це під час cron/import, воно може виконуватись під PHP-FPM, але на іншому ендпоінті або навіть в іншому пулі.
2) Читайте логи, в яких захована правда
- Лог помилок PHP-FPM (стек пам’яті при вичерпанні, ім’я пулу).
- Лог веб-сервера (шлях запиту, апстрім, тайм-аути).
- Лог відладки WordPress (якщо увімкнено) для останнього виконаного коду плагіна/теми.
3) Виміряйте реальне споживання пам’яті на запит
- Якщо один запит підскакує до ліміту: у вас важка сторінка (часто викликана плагіном).
- Якщо пам’ять росте з часом через запити: можлива модель витоку (частіше з персистентними воркерами + кешуванням в статичних змінних).
4) Застосуйте найменший безпечний пом’якшувальний захід
- Підніміть
memory_limitпомірно (256M → 512M типово для складних адмін-стеків). - Збільшуйте лише для пулу/сайту, який цього потребує, а не для всього сервера.
- Перевірте знову конкретну дію, що валилось (оновлення плагіна, завантаження медіа, генерація звіту).
5) Виправте базове навантаження
- Вимкніть або замініть плагін-«поїдач пам’яті».
- Виправте надмірні автозавантажені опції.
- Пагінуйте запити, зменшіть віджети в адмінці та виправте інструменти імпорту/експорту.
Правило: налаштування пам’яті — це пластир, поки ви не доведете, що навантаження здорове.
Кореневі причини, які ви справді можете виправити
Причина A: Ви змінили не ту ручку
Є кілька «лімітів пам’яті» в справі:
- PHP
memory_limit: реальний кап. Встановлюється в php.ini, конфігу пулу або через runtime overrides. WP_MEMORY_LIMIT/WP_MAX_MEMORY_LIMIT: WordPress просить ліміт, але PHP може відмовити, якщо він налаштований нижче.- Значення в панелі хостингу: часто записуються в один ini-файл, але фактичний FPM пул завантажує інший.
- Обмеження контейнера (cgroups): якщо ви в Docker/Kubernetes, контейнер може бути обмежений, навіть якщо PHP каже «512M».
Причина B: Плагін або тема будує величезні масиви (часто випадково)
Типові патерни:
- Завантаження всіх постів/користувачів/замовлень без пагінації («просто для випадаючого списку»).
- Запуск важких аналітик у PHP замість SQL.
- Отримання віддалених API і кешування цілих відповідей в пам’яті.
- Рекурсивний рендеринг або вкладені шорткоди, що вибухають за розміром контенту.
Причина C: Здуття автозавантажених опцій
WordPress завантажує всі опції з autoload = 'yes' на кожен запит. Якщо цей набір рядків стає мегабайтним серіалізованим сміттям, кожен запит платить за це. Адмін платитиме більше, бо він виконує більше дій. Це тихий вбивця на сайтах, що «раніше працювали».
Причина D: Обробка медіа та великі завантаження
Зміна розміру зображень може виділяти великі буфери. Те ж саме стосується генерації мініатюр PDF, парсингу EXIF і плагінів «оптимізувати зображення при завантаженні». Спайки пам’яті нормальні; повторні спайки, які потрапляють у ваш ліміт — ні.
Причина E: Колізії cron і фонова робота
Якщо WP-Cron запускає важку роботу під час активності адміністратора, ви отримуєте конкуренцію за пам’ять і виснаження воркерів. Помилка може з’явитись на не пов’язаних сторінках адмінки, бо пул під навантаженням і воркери перезапускаються в невдалий час.
Причина F: Розмір пулу PHP-FPM як у фентезійному романі
Якщо кожен PHP-FPM воркер може використовувати до 512M, а ви дозволяєте 20 дочірніх процесів, ви пообіцяли ядру 10GB пам’яті, якої може не бути. Linux покаже реальність через свап, OOM kills і сум. Ваша проблема пам’яті WordPress перетвориться на відмову сервера.
Причина G: Неправильне налаштування OPcache
OPcache допомагає, але неправильне розмірення призводить до частих рестартів або трешу кешу. Це може посилити піки пам’яті під час перекомпіляції і збільшити затримку запитів, що спричинить більше одночасних воркерів (а отже більше пам’яті).
Одна перефразована ідея від Werner Vogels (CTO Amazon): Все ламається, тож проектуйте системи, які очікують відмов і швидко відновлюються.
Такий підхід тут працює: будуйте ліміти, які не дозволять плагіну вивести сайт з ладу.
Практичні завдання: команди, виводи, рішення (12+)
Ці завдання припускають типовий Linux-сервер з Nginx + PHP-FPM або Apache. Підганяйте шляхи під ваш дистрибутив. Кожне завдання містить: команду, приклад виводу, що це означає і яке рішення прийняти.
Завдання 1: Визначити, який бінарний PHP використовується (CLI)
cr0x@server:~$ php -v
PHP 8.2.12 (cli) (built: Oct 10 2024 10:11:05) (NTS)
Copyright (c) The PHP Group
Zend Engine v4.2.12, Copyright (c) Zend Technologies
with Zend OPcache v8.2.12, Copyright (c), by Zend Technologies
Значення: Це CLI PHP. WP-CLI використовує цей, якщо не налаштовано інше.
Рішення: Якщо помилка відбувається в WP-CLI (імпорти, оновлення), виправляйте шлях ini та memory_limit для CLI, а не тільки FPM.
Завдання 2: Знайти, які ini-файли завантажує CLI PHP
cr0x@server:~$ php --ini
Configuration File (php.ini) Path: /etc/php/8.2/cli
Loaded Configuration File: /etc/php/8.2/cli/php.ini
Scan for additional .ini files in: /etc/php/8.2/cli/conf.d
Additional .ini files parsed: /etc/php/8.2/cli/conf.d/10-opcache.ini
/etc/php/8.2/cli/conf.d/20-mysqli.ini
Значення: Звідси походить CLI memory_limit.
Рішення: Якщо CLI-завдання падають, редагуйте /etc/php/8.2/cli/php.ini (або додайте override ini), а не міняйте налаштування FPM і дивуйтесь, чому нічого не змінюється.
Завдання 3: Перевірити поточний CLI memory_limit
cr0x@server:~$ php -r 'echo ini_get("memory_limit"), PHP_EOL;'
128M
Значення: CLI-завдання обмежено 128M.
Рішення: Для важких WP-CLI операцій підвищте це (часто до 512M або 1024M), або використовуйте тимчасові php -d memory_limit=....
Завдання 4: Перевірити сервіс і версію PHP-FPM
cr0x@server:~$ systemctl status php8.2-fpm --no-pager
● php8.2-fpm.service - The PHP 8.2 FastCGI Process Manager
Loaded: loaded (/lib/systemd/system/php8.2-fpm.service; enabled)
Active: active (running) since Fri 2025-12-27 08:41:10 UTC; 2h 11min ago
Docs: man:php-fpm8.2(8)
Main PID: 1134 (php-fpm8.2)
Tasks: 34 (limit: 18970)
Memory: 612.3M
Значення: PHP-FPM запущений; пам’ять тут — це загалом по воркерам.
Рішення: Якщо сервіс часто перезапускається або споживання пам’яті велике, ймовірно проблеми з розміром пулу або патерном запитів-«жерців пам’яті».
Завдання 5: Знайти конфіг пулу PHP-FPM, який обслуговує сайт
cr0x@server:~$ grep -R "listen =" -n /etc/php/8.2/fpm/pool.d
/etc/php/8.2/fpm/pool.d/www.conf:41:listen = /run/php/php8.2-fpm.sock
/etc/php/8.2/fpm/pool.d/siteA.conf:33:listen = /run/php/php8.2-fpm-siteA.sock
Значення: Є кілька пулів. Ваш сайт може не використовувати www.
Рішення: Визначте сокет, який використовує ваш vhost, і налаштуйте правильний пул. Редагування неправильного пулу — класичний «я ж казав, я змінив» інцидент.
Завдання 6: Підтвердити, що Nginx вказує на очікуваний FPM-сокет
cr0x@server:~$ sudo nginx -T 2>/dev/null | grep -n "fastcgi_pass" | head
218: fastcgi_pass unix:/run/php/php8.2-fpm-siteA.sock;
401: fastcgi_pass unix:/run/php/php8.2-fpm.sock;
Значення: Різні server block-и використовують різні пула.
Рішення: Вносьте зміни memory_limit та розміру пулу саме в той пул, який використовує WordPress vhost.
Завдання 7: Перевірити чи є у пулі FPM переоприділення memory_limit
cr0x@server:~$ sudo grep -nE "php_admin_value\[memory_limit\]|php_value\[memory_limit\]" /etc/php/8.2/fpm/pool.d/siteA.conf
55:php_admin_value[memory_limit] = 256M
Значення: Пул жорстко обмежує PHP до 256M незалежно від wp-config.php.
Рішення: Якщо адмінські дії перевищують 256M, підніміть це помірно (наприклад, до 512M) і перераховуйте pm.max_children, щоб уникнути ризику OOM.
Завдання 8: Безпечно перезавантажити PHP-FPM після змін
cr0x@server:~$ sudo systemctl reload php8.2-fpm
Значення: Reload застосовує конфіг без скидання всіх з’єднань (зазвичай).
Рішення: В продакшні віддавайте перевагу reload над restart. Якщо reload падає, перевірте синтаксис і логи перед перезапуском.
Завдання 9: Підтвердити memory_limit, який бачить FPM через тимчасовий ендпоінт
cr0x@server:~$ printf '%s\n' '/dev/null
cr0x@server:~$ curl -sS http://127.0.0.1/mem.php
256M
Значення: PHP, виконаний через веб, бачить 256M.
Рішення: Якщо ви очікували 512M, але отримали 256M, ви все ще редагуєте не той файл конфігурації, не той пул або кеш/проксі вказує на інший vhost.
Завдання 10: Переглянути slowlog і error log PHP-FPM на сліди вичерпання пам’яті
cr0x@server:~$ sudo tail -n 30 /var/log/php8.2-fpm.log
[27-Dec-2025 10:42:18] WARNING: [pool siteA] child 20211, script '/var/www/siteA/public/wp-admin/admin-ajax.php' (request: "POST /wp-admin/admin-ajax.php") executing too slow (5.123 sec), logging
[27-Dec-2025 10:42:18] PHP Fatal error: Allowed memory size of 268435456 bytes exhausted (tried to allocate 65536 bytes) in /var/www/siteA/public/wp-content/plugins/some-plugin/includes/report.php on line 812
Значення: Названо збійний ендпоінт і файл плагіна, що винуватить. Це золото.
Рішення: Не просто піднімайте пам’ять. Розслідуйте дію плагіна (генерація звіту через AJAX) і вирішіть вимкнути, запатчити або змінити його налаштування.
Завдання 11: Вимкнути плагіни без wp-admin (WP-CLI)
cr0x@server:~$ cd /var/www/siteA/public
cr0x@server:~$ sudo -u www-data wp plugin list --status=active
+----------------------+----------+-----------+---------+
| name | status | update | version |
+----------------------+----------+-----------+---------+
| woocommerce | active | none | 8.5.2 |
| some-plugin | active | none | 3.1.0 |
| cache-plugin | active | available | 2.9.1 |
+----------------------+----------+-----------+---------+
cr0x@server:~$ sudo -u www-data wp plugin deactivate some-plugin
Plugin 'some-plugin' deactivated.
Значення: Ви можете відновити доступ до адмінки без кліків у зламаному інтерфейсі.
Рішення: Якщо деактивація зупинила вичерпання пам’яті, ви ізолювали винуватця. Тримайте його вимкненим, поки не відтворите проблему в staging і не виправите належним чином.
Жарт 1: Вимкнути плагін щоб врятувати продакшн — це як вимкнути сигналізатор диму, бо на кухні пожежа. Працює, але будь ласка, ще й загасіть вогонь.
Завдання 12: Перевірити константи пам’яті WordPress (wp-config.php)
cr0x@server:~$ grep -nE "WP_MEMORY_LIMIT|WP_MAX_MEMORY_LIMIT" /var/www/siteA/public/wp-config.php
91:define('WP_MEMORY_LIMIT', '256M');
92:define('WP_MAX_MEMORY_LIMIT', '512M');
Значення: WordPress просить 512M для адмінки.
Рішення: Якщо PHP-FPM все ще на 256M — підніміть memory_limit у FPM. Якщо FPM вже на 512M і ви все ще падаєте — виправляйте навантаження.
Завдання 13: Виявити здуття автозавантажених опцій у MySQL
cr0x@server:~$ mysql -N -e "SELECT ROUND(SUM(LENGTH(option_value))/1024/1024,2) AS autoload_mb FROM wp_options WHERE autoload='yes';"
8.74
Значення: Майже 9MB автозавантажених опцій завантажуються на кожен запит. Це не округлення.
Рішення: Все, що вище ~1–2MB варто дослідити. Вище ~5MB — очікуйте проблем з продуктивністю та пам’яттю. Знайдіть найбільших «порушників» і зупиніть їх автозавантаження.
Завдання 14: Знайти гірших «порушників» автозавантаження
cr0x@server:~$ mysql -N -e "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 10;"
some_plugin_cache 3.12
builder_global_settings 1.47
woocommerce_sessions 0.88
theme_mods_mytheme 0.62
Значення: Кілька опцій домінують у відбитку.
Рішення: Для опцій, які не повинні автозавантажуватись, змініть autoload на ‘no’ і переконайтесь, що плагін з цим працює. Якщо не працює — замініть або запатчіть плагін.
Завдання 15: Вимкнути автозавантаження для конкретної опції (обережно)
cr0x@server:~$ mysql -e "UPDATE wp_options SET autoload='no' WHERE option_name='some_plugin_cache';"
cr0x@server:~$ mysql -N -e "SELECT option_name, autoload FROM wp_options WHERE option_name='some_plugin_cache';"
some_plugin_cache no
Значення: Опція більше не завантажуватиметься на кожен запит.
Рішення: Протестуйте адмін-флоти, що залежали від неї. Якщо щось ламається — відкотіть і вирішіть інакше (налаштування плагіна, бекенд кешу або заміна плагіна).
Завдання 16: Інспектувати пам’ять процесів PHP-FPM у реальному світі
cr0x@server:~$ ps -o pid,pmem,rss,cmd -C php-fpm8.2 --sort=-rss | head
PID %MEM RSS CMD
20211 2.6 214336 php-fpm: pool siteA
20219 2.5 208912 php-fpm: pool siteA
20205 1.8 146220 php-fpm: pool siteA
Значення: RSS показує реальну резидентну пам’ять. Воркери зараз близько ~200MB кожен.
Рішення: Використовуйте це для розрахунку pm.max_children. Якщо кожен child ~200MB і ви можете виділити 2GB для PHP-воркерів, не запускайте 20 дітей.
Завдання 17: Перевірити обмеження cgroup/контейнера (якщо застосовно)
cr0x@server:~$ cat /sys/fs/cgroup/memory.max 2>/dev/null || true
1073741824
Значення: Процес обмежений 1GB cgroups (значення в байтах). Це максимум для всього в контейнері.
Рішення: Якщо ви встановили PHP на 512M і дозволили кілька воркерів, ви вдаритесь у OOM контейнера. Налаштуйте обмеження контейнера або кількість воркерів.
Завдання 18: Перевірити розмір і поведінку OPcache
cr0x@server:~$ php -r 'print_r(opcache_get_status(false)["memory_usage"]);'
Array
(
[used_memory] => 78120384
[free_memory] => 26345472
[wasted_memory] => 4128768
[current_wasted_percentage] => 4.72
)
Значення: У OPcache обмежено вільну пам’ять; wasted — помірний.
Рішення: Якщо вільної пам’яті майже немає і wasted зростає, збільшіть opcache.memory_consumption та/або налаштуйте revalidate. Якщо OPcache часто скидається, затримка запитів і пікова конкуренція можуть зрости, збільшуючи тиск на пам’ять.
Три корпоративні історії з поля бою
Міні-історія 1: Інцидент через неправильне припущення
Компанія мала «прості» WordPress: маркетинговий сайт, кілька лендингів і блог. Потім додали WooCommerce «лише для кількох товарів». Ніхто не змінив тариф хостингу, бо це «лише плагін».
Через два тижні фінанси попросили звіт по замовленнях. Менеджер натиснув «Експорт CSV» з адмінки. Сторінка зависла, потім впала з фатальною помилкою вичерпання пам’яті. Спробували ще раз. Те саме. Потім ще раз, бо люди — істоти послідовні.
Он-кол інженер підняв WP_MAX_MEMORY_LIMIT до 512M, але крах тривав. Підняли до 1024M. Все одно. Дійшли висновку, що сервер «занадто малий» і попросили більший VM.
Справжня причина була в тому, що PHP-FPM мав пулове переоприділення php_admin_value[memory_limit] = 256M з моменту міграції зі шаред-хостингу. WordPress ввічливо просив більше пам’яті, а PHP ввічливо відмовляв.
Після того як команда виправила правильний конфіг пулу і підвищила ліміт до 512M, експорт пройшов — але займав дуже багато часу і викликав піки пам’яті воркерів. Це привело до другого уроку: метод експорту завантажував всі замовлення в масиви PHP. Пізніше його замінили на пагінований експорт, що стрімить рядки. Пам’ять перестала бути регулярною причиною інцидентів.
Міні-історія 2: Оптимізація, що відкотилася
Інша організація вирішила «оптимізувати», звузивши memory_limit у всіх пулах PHP. Логіка здавалася розумною: менші ліміти запобіжать неконтрольованим скриптам. Вони встановили memory_limit до 128M скрізь і потішилися дисципліною.
Місяць усе було добре. Потім запустили сезонну кампанію і редактори завантажували багато високороздільних зображень. WordPress почав генерувати кілька розмірів, декілька плагінів робили «сmart compression», і для медійних комплектів генерувалися прев’ю PDF.
Раптом завантаження час від часу падали з помилкою вичерпання пам’яті. «Час від часу» — ключове слово: маленькі зображення працювали, великі — помирали. Підтримці було важко відтворити, якщо не використовувати ті самі файли.
«Оптимізація» підвищила частоту відмов, бо видалила бурст-ємність, потрібну для легітимних навантажень. Врешті вони підняли пам’ять для пула обробки медіа до 512M і винесли важкі трансформації в чергу з окремими воркерами з більшим запасом пам’яті.
Нижчий ліміт для фронтенд-пулів вони залишили — це було правильно. Промах став у припущенні, що одне число підходить для всіх навантажень.
Міні-історія 3: Нудна, але правильна практика, що врятувала вечір
Більша компанія запускала десятки WordPress-сайтів за стандартними Nginx і PHP-FPM пулами. Нічого особливого. Секрет — нудний: пер-сайт пула, явні ліміти і метрики RSS воркерів.
Коли один сайт почав викидати помилки вичерпання пам’яті після оновлення плагіна, он-кол не сперечався в Slack годинами. Вони перевірили недавній розподіл RSS пулу і побачили, що пам’ять воркерів подвоїлася після оновлення. Це звузило пошук від «WordPress зламався» до «цей плагін змінив поведінку».
Вони відкотили версію плагіна (також нудно), відновили сервіс і потім відтворили проблему в staging з таким же набором даних. Плагін кешував велику відповідь API в автозавантаженій опції — і кожен запит платив за це.
Оскільки у них вже був чекліст «autoload bloat», вони швидко це помітили, виправили і додали гвардію: автоматичну перевірку, що сигналізує, коли автозавантажені опції перевищують поріг.
Це не приносило нагород. Але це запобігло бійці о 3 ранку. Такий успіх ви цінуєте лише після протилежного досвіду.
Поширені помилки: симптом → корінь → виправлення
1) Симптом: Ви встановили WP_MEMORY_LIMIT, але помилка все ще показує старе значення в байтах
Корінь: PHP обмежений нижче за WordPress-константи (переоприділення пулу, php.ini для FPM або невідповідність панелі хостингу).
Виправлення: Підтвердьте memory_limit через веб-ендпоінт (Завдання 9) і змініть правильний конфіг пулу FPM (Завдання 7), потім перезавантажте FPM (Завдання 8).
2) Симптом: WP-CLI команди падають з помилкою пам’яті, але wp-admin в порядку
Корінь: CLI php.ini має нижчий memory_limit, ніж FPM.
Виправлення: Перевірте php --ini і php -r 'ini_get(...)' (Завдання 2–3). Підніміть CLI memory_limit або використайте php -d memory_limit=... для конкретних задач.
3) Симптом: Лише завантаження медіа падають; звичайні сторінки адмінки працюють
Корінь: Обробка зображень/PDF спричиняє спайки пам’яті; плагіни додають додаткові трансформації.
Виправлення: Підвищте ліміт для пулу, що обробляє завантаження; зменшіть агресивність оптимізації зображень; винесіть трансформації; перевірте post_max_size і upload_max_filesize (не охоплено цією помилкою, але часто йдуть разом).
4) Симптом: Випадкові адмін-сторінки вмирають «після певного часу», особливо під навантаженням
Корінь: Пул FPM перенавантажений; зависокий рівень дітей; свап; OOM kills; або накопичення пам’яті у воркера за час життя.
Виправлення: Виміряйте RSS воркерів (Завдання 16), встановіть pm.max_children на основі бюджету пам’яті, увімкніть pm.max_requests для періодичного перезапуску воркерів і шукайте плагін, що накопичує пам’ять у персистентних воркерах.
5) Симптом: Після вмикання кеш-плагіна помилки пам’яті стали гірші
Корінь: Об’єктне кешування в масивах PHP, автозавантажене здуття або кешування фрагментів сторінки в пам’яті на запит.
Виправлення: Перевірте розмір автозавантаження (Завдання 13–15), налаштуйте зовнішній бекенд об’єктного кешу за потреби і уникайте кешування цілих наборів даних в опціях.
6) Симптом: Збільшення memory_limit вирішило проблему… на тиждень
Корінь: Зростання даних або повільний витік (автозавантажені опції ростуть, логи зберігаються в опціях, transient-бліт, оновлення плагіна).
Виправлення: Трекінгуйте тренди автозавантажених опцій, розподіл RSS воркерів і кількість помилок. Визначте зростаючі таблиці/опції і прочистіть/виправте джерело.
7) Симптом: Ви встановили дуже високий memory_limit і тепер сервер нестабільний
Корінь: Ви підняли ліміти на процес без зменшення конкурентності. Ядро не може заплатити обіцяний рахунок пам’яті.
Виправлення: Зменшіть pm.max_children, встановіть реалістичний memory_limit і використовуйте черги для важких задач. Необмежена пам’ять — це антипатерн продуктивності в плащі.
Жарт 2: Встановити memory_limit = -1 — як прибрати спідометр, бо не подобаються штрафи за швидкість. Стіна все одно є.
Чеклісти / покроковий план (постійні виправлення)
План крок за кроком: стабілізувати, а потім зафіксувати
Фаза 1: Повернути доступ до wp-admin (15–30 хвилин)
- Знайдіть збійний ендпоінт і винуватця у логах PHP-FPM (Завдання 10). Якщо ви не знаєте, що впало — ви гадаєте.
- Вимкніть підозрілий плагін через WP-CLI (Завдання 11) або тимчасово перемістіть його директорію з
wp-content/plugins. - Підтвердьте фактичний
memory_limit, який використовує сайт, через файлmem.php(Завдання 9), потім видаліть цей файл. - Помірно підніміть
memory_limitпулу (256M → 512M) за потреби (Завдання 7), перезавантажте FPM (Завдання 8).
Фаза 2: Зробити пам’ять прогнозованою (того ж дня)
- Виміряйте RSS воркерів і встановіть
pm.max_childrenна основі реальних даних, а не сподівань (Завдання 16). - Додайте перезапуск воркерів через
pm.max_requests(починайте з ~300–1000 залежно від стабільності коду). Це обмежить довготривале накопичення пам’яті. - Зупиніть автозавантажене здуття: виміряйте розмір (Завдання 13), перелічіть порушників (Завдання 14), поміняйте autoload для неважливих блобів (Завдання 15) і виправте поведінку плагіна.
- Розділіть пула для важких навантажень (адмінка/медіа/імпорт) якщо можете. Різні ліміти, різна конкурентність, менше сюрпризів.
Фаза 3: Виправити навантаження (тиждень 1)
- Відтворіть у staging з даними, схожими на прод. Більшість «тільки в прод» проблем з пам’яттю — це питання розміру даних.
- Замініть або запатчіть плагін-«жерця пам’яті». Плагіни, що завантажують усе в пам’ять, — ризик для продакшну.
- Стрімуйте експорти/імпорти: чанковані читання, пагінація запитів, інкрементальний запис результату і уникнення побудови гігантських масивів.
- Виносьте важкі задачі з шляху запиту через реальний cron і чергу/воркери. Запити мають бути швидкими; задачі — важкими.
Чекліст: Розмір пулу PHP-FPM, що не OOM-ить вашу машину
- Виміряйте типову і пікову RSS на воркер (
ps, Завдання 16). - Визначте бюджет пам’яті для PHP-воркерів (наприклад, 40–60% RAM після DB, кешу, OS).
- Обчисліть
pm.max_children≈ бюджет / піковий RSS (округлити вниз). - Встановіть
pm = dynamicз адекватнимиpm.start_servers,pm.min_spare_servers,pm.max_spare_servers. - Встановіть
pm.max_requestsдля періодичного перезапуску. - Тримайте
memory_limitдостатньо високим для легітимних адмінських операцій, але не настільки високим, щоб один запит міг залишити хост без ресурсів.
Чекліст: WordPress-гігієна, що запобігає вибухам пам’яті
- Тримайте автозавантажені опції легкими; налаштуйте алерти при зростанні autoload MB понад поріг.
- Аудит плагінів щоквартально: видаляйте занедбані, замінюйте важкі і позбувайтесь дублювання функцій.
- Використовуйте WP-CLI для контрольованих масових операцій з явними лімітами пам’яті.
- Зробіть WP-Cron справжнім cron, щоб завдання запускалися за розкладом, а не під час запитів користувачів.
- Слідкуйте за використанням admin-ajax; саме там «невеликий звіт» перетворюється на 500MB запит.
FAQ
1) Це «Allowed memory size exhausted» — обмеження WordPress чи PHP?
Це обмеження PHP. WordPress може просити більше пам’яті через константи, але PHP встановлює фактичний кап.
2) Я встановив define('WP_MEMORY_LIMIT','512M'). Чому все ще падає?
Тому що PHP все ще обмежений нижче (переоприділення пулу, php.ini для FPM або обмеження контейнера). Перевірте через веб-ендпоінт (Завдання 9) і виправте правильний пул (Завдання 5–7).
3) Який sane memory_limit для адмінки WordPress?
Для простого сайту 256M часто вистачає. Для WooCommerce/конструкторів сторінок/важких адмін-аналітик 512M — звичайне значення. Вище цього — це запах проблем і варто шукати здуття.
4) Чи слід ставити WP_MAX_MEMORY_LIMIT вищим за WP_MEMORY_LIMIT?
Так. Фронтенд-запити зазвичай легші і передбачуваніші. Адмінка може потребувати більше для оновлень, медіа, експорту та дашбордів.
5) Чи може OPcache викликати помилки вичерпання пам’яті?
OPcache не рахується проти memory_limit так само (використовує shared memory), але неправильні налаштування OPcache можуть збільшити затримки й конкуренцію, опосередковано підвищуючи загальне навантаження пам’яті воркерів.
6) Якщо я підвищу memory_limit, чи може це погіршити продуктивність?
Так, якщо ви не підкоригуєте конкурентність. Більші ліміти на воркерів при незмінному pm.max_children можуть призвести до свапу або OOM. Налаштовуйте системно.
7) Чому це трапляється лише на певних сторінках адмінки?
Ці сторінки запускають важчі шляхи коду: генерація звітів, пакетні операції, трансформації медіа або плагіни, що запитують надмірні дані. Логи (Завдання 10) зазвичай показують файл винуватця.
8) Який найшвидший безпечний спосіб відновити доступ, якщо wp-admin мертвий?
Вимкніть підозрілий плагін через WP-CLI (Завдання 11) або перемістіть його директорію. Потім виправте корінь проблеми перед повторним вмикненням.
9) Чи може блоат у базі даних спричинити вичерпання пам’яті PHP?
Опосередковано — так. Величезні опційні блоби (особливо автозавантажені) і необмежені запити можуть завантажити великі набори результатів у пам’ять PHP. Виміряйте autoload (Завдання 13) і виправте порушників (Завдання 14).
10) Як запобігти цьому після оновлень плагінів?
Тестуйте у staging з реальними даними, моніторьте тренди RSS воркерів, тримайте алерти на зростання autoload MB і керуйте політикою плагінів. Фаза «встановити що завгодно» закінчується, коли починається продакшн.
Висновок: що робити далі
Якщо хочете це виправити раз і назавжди — перестаньте сприймати вичерпання пам’яті як одну налаштування. Це поведінка системи.
- Сьогодні: Використайте логи, щоб знайти збійний ендпоінт і плагін, перевірте фактичний
memory_limitдля веба та CLI і стабілізуйте ситуацію консервативним підняттям, якщо потрібно. - На цьому тижні: Виміряйте RSS воркерів, встановіть конкурентність PHP-FPM на базі бюджету, перезапускайте воркерів і почистіть автозавантажені опції.
- Постійно: Ставтеся до змін плагінів як до змін коду — тестуйте, вимірюйте і швидко відкочуйте. Додайте алерти на зростання autoload і кількість помилок пам’яті.
Зробіть це — і «Allowed memory size exhausted» знову стане тим, чим має бути: рідкісним запобіжником, а не регулярною проблемою у календарі.