php-fpm: Allowed memory size exhausted
Предел памяти PHP ограничивает один запрос, а не весь пул. Исчерпание даёт ошибку в журнале и обрыв запроса, но службу не роняет. Это защита: без неё один тяжёлый запрос мог бы съесть память машины.
Вероятные причины
По порядку: сверху то, что встречается чаще.
-
Предел мал для этой операции
Выгрузка отчёта, обработка изображения, импорт данных требуют больше памяти, чем обычный запрос.
-
Утечка памяти в приложении
Если предел исчерпывается на обычных запросах, дело не в пределе. Признак — рост потребления при однотипных обращениях.
-
Предел памяти пула и предел службы не согласованы
Предел PHP на запрос, умноженный на число рабочих процессов, может превысить предел памяти службы. Тогда пул будут убивать целиком.
Диагностика
Команды идут в том порядке, в котором их стоит выполнять: каждая следующая проверяет то, что осталось после предыдущей.
Какие запросы исчерпывают предел.
sudo tail -30 /var/log/php8.3-fpm.log | grep -i "memory size"Действующие пределы PHP.
php -i | grep -E "memory_limit|max_execution_time"Потребление пула и предел службы.
systemctl show php8.3-fpm -p MemoryPeak -p MemoryMaxРешение
Решение своё для каждой причины. Сначала определите, какая из них ваша, — иначе правки наложатся друг на друга.
- Почему происходит
- Выгрузка отчёта, обработка изображения, импорт данных требуют больше памяти, чем обычный запрос.
- Как проверить
-
Посмотрите предел и сообщение.
php -i 2>/dev/null | grep memory_limit sudo tail -20 /var/log/php8.3-fpm.log | grep -i "memory size"
- Как исправить
-
Поднимите предел для нужного пула или для конкретного пути, а не глобально: глобальный рост умножается на число рабочих процессов.
# в описании пула: # php_admin_value[memory_limit] = 512M sudo systemctl reload php8.3-fpm
- Почему происходит
- Если предел исчерпывается на обычных запросах, дело не в пределе. Признак — рост потребления при однотипных обращениях.
- Как проверить
-
Посмотрите частоту сообщений и потребление пула.
sudo grep -c "memory size" /var/log/php8.3-fpm.log systemctl show php8.3-fpm -p MemoryCurrent -p MemoryPeak
- Как исправить
- Разбирайтесь с приложением. Поднятие предела при утечке лишь отодвигает отказ и увеличивает риск для машины.
- Почему происходит
- Предел PHP на запрос, умноженный на число рабочих процессов, может превысить предел памяти службы. Тогда пул будут убивать целиком.
- Как проверить
-
Сравните три числа.
grep -E "^pm.max_children" /etc/php/8.3/fpm/pool.d/www.conf php -i | grep memory_limit systemctl show php8.3-fpm -p MemoryMax
- Как исправить
- Согласуйте: предел службы должен быть больше произведения с запасом, иначе ограничение бессмысленно.
Пример вывода
Скрипт исчерпал предел памяти на выгрузке отчёта. Пример показательный: он собран на тестовой машине специально для этой страницы, а не взят из чужого журнала.
php-fpm8.3[1200]: [WARNING] [pool www] child 4100 said into stderr: "PHP Fatal error: Allowed memory size of 134217728 bytes exhausted (tried to allocate 20480 bytes) in /var/www/app/report.php on line 88"
Связанные ошибки
- php-fpm: server reached pm.max_children setting Пул php-fpm исчерпал рабочие процессы: сайт отвечает медленно или отдаёт 502. Как считать pm.max_children.
- Failed with result 'oom-kill' Состояние oom-kill: процесс службы убит из-за нехватки памяти. Как понять, упёрлись в предел службы или в память машины.
- nginx 502 Bad Gateway: connect() failed к приложению nginx работает, а приложение недоступно: connect() failed, connection refused, no such file or directory для сокета. Разбор 502.
- Cannot allocate memory в журнале службы Не удалось выделить память: предел службы, память машины, настройка overcommit, исчерпанные области отображения.
- Elasticsearch: служба падает из-за размера кучи JVM Размер кучи больше доступной памяти или больше предела службы: падение при старте или под нагрузкой.
- Hardware Error / EDAC: ошибки памяти в журнале Ядро сообщает об ошибках памяти. Что считать безобидным, а что поводом менять модуль.
- Java-служба: OutOfMemoryError и куча Служба на JVM падает с нехваткой памяти: размер кучи, предел контрольной группы, дампы кучи.
- MySQL убит из-за памяти: буферный пул больше доступной памяти MySQL падает сразу после старта или через минуты: размер innodb_buffer_pool_size превышает память машины.
Где встречается чаще всего
Источники
- Документация PHP: memory_limit
-
Воспроизведено на тестовой машине, systemd 255 (Ubuntu 24.04)
Воспроизведено скриптом, выделяющим больше предела.