#Что происходит и когда применима инструкция
Ошибка Allowed memory size exhausted означает, что скрипт достиг установленного для процесса лимита memory_limit при попытке выделить дополнительную память. При обработке массивов причиной часто бывает построение нескольких полных копий данных, рекурсивная сериализация либо чтение всей выборки в память.
#Причины и диагностические признаки
| Возможная причина | Как узнать | Что делать |
|---|---|---|
| Массив загружается целикомМассив загружается целиком. Потребление резко растёт при fetchAll(), file() или накоплении строк в цикле. | Потребление резко растёт при fetchAll(), file() или накоплении строк в цикле. | Перейти на потоковую либо постраничную обработку. |
| Данные дублируются при преобразованииДанные дублируются при преобразовании. Создание нескольких крупных структур/кодов JSON приводит к пику RAM. | Создание нескольких крупных структур/кодов JSON приводит к пику RAM. | Измерить размер промежуточных значений и уменьшить копии. |
| Лимит PHP ниже ожидаемогоЛимит PHP ниже ожидаемого. CLI завершается успешно, веб-FPM ограничен меньшим memory_limit. | CLI завершается успешно, веб-FPM ограничен меньшим memory_limit. | Сверить значения в реальном веб-пуле. |
#Подробная пошаговая инструкция
- Запишите точное сообщение и место сбояВ журнале PHP найдите Allowed memory size of … bytes exhausted (tried to allocate … bytes) и строку PHP-файла. Это не обязательно означает, что требуется памяти ровно столько, сколько указано в tried to allocate: там размер последнего неудачного выделения.
- Проверьте объём исходных данных и кратность копийНа тестовой копии воспроизведите обработку малого, среднего и большого набора. Запишите количество элементов, средний размер строки и время. Для чувствительных данных используйте обезличенный образец и не сохраняйте полный массив в журнал.
- Измерьте расход памяти по контрольным точкамДобавьте временную отладочную запись memory_get_usage(true) и memory_get_peak_usage(true) перед загрузкой массива, после неё и после преобразования. Выводите только числа и этапы, не сами данные. Затем уберите диагностику из рабочего кода.
- SSH, читает CLI-лимитLinux · Терминал (Bash)КомандаSSH, читает CLI-лимит. В FPM значение может быть другим; проверьте веб-окружение через закрытый маршрут.
php -r "echo ini_get("memory_limit"), PHP_EOL;"
- Замените полную загрузку потоковой обработкойЕсли в коде fetchAll() забирает огромную таблицу, используйте последовательное чтение через fetch() и обрабатывайте результаты по одному, если драйвер и тип запроса позволяют избежать полной буферизации. При работе с CSV читайте строки в цикле fgets/fgetcsv; в БД используйте постраничную выборку или курсор по возможностям драйвера.
- Исправьте рост массива в циклеЕсли программа хранит каждую обработанную запись, спросите, нужно ли это дальше. Передавайте результат в файл/БД порциями вместо накопления всего списка. Проверьте, что новый алгоритм не меняет порядок данных и не допускает дубли при повторном запуске после сбоя.
- Если лимит действительно недостаточен, рассчитайте безопасную границуОцените пиковую память процесса, количество одновременных обработчиков FPM и запас сервера. Поднять memory_limit с 128M до 256M можно только после расчёта; при десятках работников это многократно увеличивает потенциальное использование RAM. Не ставьте -1 без обоснования.
- Проверьте настройку в реальном обработчике сайтаНастройте memory_limit в панели или разрешённой конфигурации пула, сохраните резервную копию, выполните проверку FPM и перечитайте его при необходимости. В закрытом веб-маршруте убедитесь, что ini_get("memory_limit") совпадает с выбранным значением.
- SSH, только чтениеLinux · Терминал (Bash)КомандаSSH, только чтение. Показывает доступную RAM и процессы с наибольшим RSS; RSS может учитывать общие страницы и не равен точной уникальной памяти.
free -h; ps -eo pid,rss,args --sort=-rss | head -n 20
- Сравните пиковый расход до и послеПовторите тестовую обработку набора того же размера, проверьте memory_get_peak_usage, отсутствие дублированных строк и число ошибок. При росте swap/OOM верните прежние лимиты и уменьшайте объём обработки.
#Как проверить, что проблема исправлена
Большая выборка обрабатывается с устойчивым потреблением памяти и без Allowed memory size exhausted, а сервер не испытывает нехватку RAM.
#Если не помогло — дальнейшая диагностика и откат
Если утечка сохраняется, профилируйте конкретный этап, проверьте расширения и алгоритмы кэширования. Простое увеличение memory_limit откладывает проблему и может перегрузить всю машину.