Allowed memory size exhausted: скрипту не хватило памяти
Текст ошибки выглядит так:
Fatal error: Allowed memory size of 268435456 bytes exhausted (tried to allocate 5243 bytes) in /home/bitrix/www/bitrix/modules/main/classes/general/database.php on line 685
Первое число — текущий лимит в байтах (268435456 это 256 МБ). Второе — сколько пытались выделить в момент падения. И вот второе число важнее первого.
Главный признак: сколько не хватило
Если в скобках мелочь — 24 байта, 5 килобайт, — а лимит при этом большой, значит память уже съедена целиком, и падение произошло на случайной мелкой операции. Увеличивать лимит в такой ситуации бесполезно: при 256 МБ упадёт на одном месте, при 1,5 ГБ — на другом, просто позже.
Если же пытались выделить много и лимит скромный, лимита действительно не хватает — тут увеличение помогает.
Где обычно падает
Место из сообщения не говорит о причине напрямую, но подсказывает, что происходило:
| Файл в сообщении | Что делал сайт |
|---|---|
modules/main/classes/general/database.php | Выбирал данные из базы: вероятно, выборка без ограничения количества |
modules/main/tools.php | Служебные операции ядра — память кончилась раньше, падение случайное |
| файлы модуля каталога или инфоблоков | Обход каталога, импорт, пересчёт |
| файлы своего компонента или шаблона | Ваш код: цикл, рекурсия, сбор всего в массив |
Когда увеличивать лимит нормально
Разовые тяжёлые операции: обновление продукта, переиндексация поиска, первая выгрузка каталога, конвертация изображений. Требование вендора — memory_limit = 256M; на время операции поднимают выше и потом возвращают.
Когда увеличивать бессмысленно
Если памяти не хватает на обычной странице сайта, лимит только отложит проблему. Смотреть нужно, что съедает память:
- Выборка без ограничения. Код запрашивает все элементы, чтобы показать десять. На каталоге в сто позиций это незаметно, на десяти тысячах — фатально.
- Обход в цикле. Для каждого элемента делается отдельный запрос, и результаты копятся в памяти.
- Рекурсия по разделам без ограничения глубины.
- Чтение больших файлов целиком вместо построчной обработки — типично для импорта.
- Утечка в стороннем модуле. Признак — падение на ровном месте при огромном лимите.
Где менять значение
- Для сайта —
php.iniдействующей версии PHP или настройки пула PHP-FPM. - Для заданий расписания — отдельный
php.iniконсольного PHP. Обмен с 1С работает именно через него. - Проверить, что применилось — проверка системы в административной части показывает действующее значение, а не то, что вы правили.
Последний пункт экономит много времени: правка не того файла настроек — самая частая причина «поменял, ничего не изменилось». На сервере несколько версий PHP, и у каждой свой набор файлов.
Отдельный случай: падает при установке
Если ошибка возникает в мастере установки продукта и лимит при этом заведомо огромный, причина не в памяти, а в несовместимости: старый дистрибутив на новой версии PHP уходит в бесконечный цикл и съедает всё, что дали. Лечится свежим дистрибутивом, а не увеличением лимита.
Если лимит поднимать некуда
- Определите по сообщению, на каком действии падает: страница каталога, экспорт, обмен, административный раздел.
- Если это своя выборка — ограничьте количество и запрашивайте только нужные поля.
- Если массовая операция — разбейте на порции с сохранением состояния между шагами.
- Если импорт из 1С — уменьшите размер порции в настройках обмена.
На сайтах, которые долго росли, нехватка памяти обычно означает, что выборки писали под каталог в тысячу позиций, а в нём уже сто тысяч. Лимит здесь — отсрочка на несколько месяцев.
Частые вопросы
Сколько памяти ставить?
Требование вендора — 256M. Для тяжёлых разовых операций поднимают выше и возвращают обратно. Постоянно держать огромное значение не стоит: оно маскирует утечки и позволяет одному запросу съесть память всего сервера.
Падает при лимите в полтора гигабайта на попытке выделить 256 килобайт.
Значит память уже съедена целиком, и падение произошло на случайной мелочи. Увеличение лимита не поможет — ищите, что её съедает: выборку без ограничения, цикл с запросами, утечку в стороннем модуле.
Поменял memory_limit, ничего не изменилось.
Скорее всего правили не тот файл. На сервере несколько версий PHP, у каждой свой php.ini, и отдельные настройки у PHP-FPM и консольного PHP. Действующее значение показывает проверка системы в административной части.
Не хватает памяти только при экспорте каталога.
Типичный случай: выгрузка собирает весь каталог в память. Такие операции делают порциями с сохранением промежуточного состояния — тогда они переживают и нехватку памяти, и обрыв связи.
Ошибка в файле database.php — это проблема базы?
Нет, просто в этот момент сайт выбирал данные. Чаще всего за этим стоит выборка без ограничения количества: код запрашивает все элементы, чтобы показать несколько.
Падает в мастере установки, хотя лимит огромный.
Похоже на несовместимость дистрибутива с версией PHP: установщик уходит в бесконечный цикл и съедает всю выделенную память. Берите свежий дистрибутив, увеличение лимита тут не поможет.