Главная » Ошибки Битрикс » Maximum execution time exceeded в Битрикс

Maximum execution time exceeded в Битрикс

Схема ограничения времени выполнения: скрипт обрывается на лимите PHP, решение — разбить операцию на шаги

Скрипт работает, работает — и обрывается на полпути. В логе появляется Maximum execution time of N seconds exceeded, импорт останавливается посередине, экспорт отдаёт обрезанный файл, а страница показывает белый экран после долгой загрузки.

PHP ограничивает время выполнения скрипта параметром max_execution_time. Разберём, где его менять, почему простое увеличение лимита помогает не всегда и как переписать долгие операции так, чтобы они вообще перестали упираться в это ограничение.

Где меняется лимит

Способов несколько, и они действуют на разных уровнях.

В php.ini

max_execution_time = 300

Действует на все скрипты. Требует доступа к конфигурации и перезапуска PHP-FPM.

В .htaccess

php_value max_execution_time 300

Работает на Apache и в связке Nginx + Apache. На чистом Nginx с PHP-FPM не сработает.

Прямо в скрипте

<?php
set_time_limit(300);   // 300 секунд с этого момента
set_time_limit(0);     // без ограничения

Самый точечный вариант: лимит поднимается только для конкретной операции, а не для всего сайта. Именно так стоит поступать с импортом и выгрузками.

Важно: set_time_limit() сбрасывает отсчёт заново при каждом вызове. Внутри длинного цикла его можно вызывать периодически, продлевая время.

Почему лимит не всегда помогает

Частая ситуация: max_execution_time подняли до 600, а скрипт всё равно обрывается на 60-й секунде. Причина в том, что ограничений несколько, и срабатывает самое строгое.

ОграничениеГде задаётсяПризнак
max_execution_time PHP Ошибка в логе PHP
request_terminate_timeout PHP-FPM Процесс убит, в логе FPM запись о таймауте
fastcgi_read_timeout Nginx Ошибка 504 Gateway Timeout
Timeout Apache Обрыв соединения
max_input_time PHP Обрыв при загрузке больших файлов

Если вместо ошибки PHP вы видите 504 — упирается Nginx, и правка max_execution_time ничего не даст. Про этот случай есть отдельный разбор: Ошибка 504 Gateway Timeout в Битрикс.

Отдельно: в командной строке ограничение времени по умолчанию отсутствует. Скрипт, который падает по таймауту через браузер, спокойно отработает через консоль.

Нужна помощь с Битрикс?





    Типичные ситуации на Битрикс

    Импорт каталога

    Загрузка большого файла товаров почти гарантированно упирается в лимит. Штатный импорт Битрикс решает это пошаговой обработкой: скрипт обрабатывает порцию записей, сохраняет позицию и перезапускается.

    Обмен с 1С

    Обмен разбит на шаги по тому же принципу. Если он обрывается, обычно дело не в самом лимите, а в слишком большом размере шага — его уменьшают в настройках обмена.

    Агенты

    Агент, выполняющийся на хите пользователя, ограничен тем же лимитом. Тяжёлому агенту место в cron, где ограничения времени нет.

    Переиндексация поиска

    Полная переиндексация большого сайта занимает часы. Запускать её нужно из командной строки, а не через административный интерфейс.

    Правильное решение: разбить на шаги

    Поднимать лимит до бесконечности — тупиковый путь: данных станет больше, и обрыв повторится. Долгие операции разбивают на порции.

    Схема пошаговой обработки:

    <?php
    
    use Bitrix\Main\Config\Option;
    
    $step      = 500;                                    // записей за проход
    $processed = (int)Option::get('mymodule', 'import_offset', 0);
    
    $result = CIBlockElement::GetList(
        ['ID' => 'ASC'],
        ['IBLOCK_ID' => 5],
        false,
        ['nTopCount' => $step, 'nOffset' => $processed],
        ['ID', 'NAME']
    );
    
    $count = 0;
    
    while ($item = $result->Fetch()) {
        // обработка одной записи
        $count++;
    }
    
    if ($count > 0) {
        // запоминаем позицию и продолжим со следующего запуска
        Option::set('mymodule', 'import_offset', $processed + $count);
    } else {
        // всё обработано, сбрасываем счётчик
        Option::set('mymodule', 'import_offset', 0);
    }

    Такой скрипт никогда не упрётся в лимит: каждый запуск занимает секунды. Запускать его можно агентом или по cron.

    Оптимизация вместо увеличения времени

    Прежде чем поднимать лимит, стоит проверить, почему операция вообще такая долгая. Частые причины на Битрикс:

    • Запрос внутри цикла. Классическая ошибка: выборка элементов, и для каждого — отдельный запрос за свойствами. Тысяча элементов превращается в тысячу запросов.
    • Выборка всех полей. Указывайте в select только нужное, особенно если у элементов много свойств.
    • Отсутствие индексов в самописных таблицах.
    • Обращение к внешнему API в цикле. Сто запросов по секунде каждый — это сто секунд только на ожидание.
    • Работа с изображениями. Генерация превью для тысячи товаров съедает и время, и память.

    Часто оптимизация одного запроса сокращает время выполнения в десятки раз — и вопрос лимита снимается сам собой.

    Диагностика

    Понять, где именно скрипт проводит время, помогают замеры:

    <?php
    
    $start = microtime(true);
    
    // ... блок кода ...
    
    \Bitrix\Main\Diag\Debug::writeToFile(
        round(microtime(true) - $start, 3) . ' сек — выборка элементов',
        'TIMING',
        '/local/logs/timing.log'
    );

    Расставив такие замеры по этапам, обычно быстро находишь один участок, который занимает почти всё время.

    Частые ошибки

    • set_time_limit(0) на боевом сайте. Зависший скрипт будет висеть вечно, занимая процесс и соединение с базой.
    • Правка max_execution_time при ошибке 504. Упирается таймаут веб-сервера, а не PHP.
    • Запуск тяжёлых операций через браузер. Для импорта и переиндексации есть командная строка без ограничений.
    • Увеличение лимита вместо оптимизации. Работает ровно до тех пор, пока данных не станет вдвое больше.
    • Тяжёлые агенты на хитах. Ограничение бьёт по случайному посетителю, которому не повезло запустить агента.

    Итог

    Ошибка Maximum execution time exceeded означает, что скрипт превысил отведённое PHP время. Поднять лимит можно через php.ini, .htaccess или точечно вызовом set_time_limit() — последний способ предпочтительнее.

    Но если операция долгая по своей природе — импорт, обмен, переиндексация — правильное решение не в лимите, а в разбиении на шаги с сохранением позиции. Такой скрипт не упрётся в ограничение никогда, сколько бы данных ни было. А перед тем как менять настройки, стоит проверить, нет ли в коде запроса внутри цикла: чаще всего время уходит именно туда.

    Нужна помощь с Битрикс?

    Исправим ошибку, доработаем сайт, ускорим Битрикс или поможем разобраться с проблемой.

    Услуги
    Инструменты
    База знаний