Я пытался улучшить стабильность нашего приложения; позволяя ему оправиться от фатальных ошибок. Метод восстановления заключается в обнаружении фатальных ошибок в зарегистрированной функции завершения работы PHP. register_shutdown_function()
используя строку:
$error = error_get_last();
это восстановит фатальную ошибку, например. недостаточно памяти, превышено время ожидания, неучтенные исключения, неопределенные функции, и т.п.
Затем ошибка может быть зарегистрирована в нашем регистраторе ошибок, и пользователь перенаправляется на безопасную страницу ошибок, где он может перейти на другую страницу. Это все отлично работает ловить недостаточно памяти а также ошибки тайм-аута за исключением следующего сценария:
примечание: использование платформы CodeIgnitor
ini_set('memory_limit', '512M');
ini_set('max_execution_time', 10);
$this->db->query('select * from massive_table');
Теперь, если в таблице mass_table, например, 9 миллионов строк, потребуется некоторое время, чтобы собрать все строки в PHP. Однако приложение вылетает без сообщения об ошибке.
Проблема появляется только тогда, когда результаты запроса будут больше, чем предел памяти, и он превысил PHP max_execution_time
,
Процесс выглядит следующим образом:
После того, как запрос был проанализирован и отправлен через драйвер MySQL, я вижу его запущенным в списке процессов MySQL. Очевидно, что для выбора 9 миллионов строк потребуется некоторое время, прежде чем он вернет значение превышения тайм-аута PHP на 10 секунд. Я бы теперь ожидал, что PHP бросит max_execution_time
достиг фатальной ошибки, однако PHP все еще ждет 10 секунд. Через некоторое время после сбоя код не сообщит о фатальной ошибке.
Если max_execution_time
достаточно высока для его возвращения, то я получу недостаточно памяти фатальная ошибка
Если memory_limit
достаточно высока, но время превышено, тогда я правильно получу max_execution_time
достиг фатальной ошибки.
Проблема только в том случае, когда оба условия достигнуты, что, кажется, проявляется только тогда, когда PHP взаимодействует с MySQL.
В журнал ошибок Apache также ничего не добавлено.
Другой побочный эффект, который заставляет меня думать, что это может быть ошибка в PHP / Apache, заключается в том, что в конкретном сценарии 9 миллионов строк (или сколько он получает до сбоя), не очищаются. Мне нужно перезагрузить Apache, чтобы очистить мою оперативную память. Я обнаружил это только тогда, когда мой компьютер остановился и заметил, что все 16 ГБ моей оперативной памяти были выделены и не очищались. Кажется, здесь может быть утечка памяти.
Задача ещё не решена.
Других решений пока нет …