Фатальная ошибка: исчерпано разрешённое объём памяти 134217728 байт
Проблема с исчерпанием памяти при отправке данных о продажах из системы POS
У меня есть несколько клиентских систем точек продажи (POS), которые периодически отправляют новые данные о продажах в одну централизованную базу данных, где эти данные сохраняются для генерации отчетов. Клиентская система POS основана на PHPPOS, и я реализовал модуль, использующий стандартную библиотеку XML-RPC для отправки данных о продажах на сервер.
Серверная часть построена на CodeIgniter и использует библиотеки XML-RPC и XML-RPCS для компонента веб-сервиса. Когда я пытаюсь отправить большое количество данных о продажах (даже всего лишь 50 записей из таблицы продаж и соответствующие строки из sales_items для каждого товара в продаже), я получаю следующую ошибку:
Fatal error: Allowed memory size of 134217728 bytes exhausted (tried to allocate 54 bytes)
Значение 128M является значением по умолчанию в файле php.ini
, но я предполагал, что это довольно большой лимит. На самом деле, я даже попытался установить это значение на 1024M, и это просто увеличивает время, прежде чем возникнет ошибка.
Что касается предпринятых мной шагов, я попробовал отключить все процессы на стороне сервера и настроил его так, чтобы он возвращал фиксированный ответ независимо от входящих данных. Тем не менее, я полагаю, что проблема заключается именно в отправке данных. Я даже попытался отключить максимальное время выполнения сценариев для PHP, но это не решило проблему.
Есть ли идеи о том, как мне решить эту проблему с исчерпанием памяти?
5 ответ(ов)
Изменение memory_limit
с помощью ini_set('memory_limit', '-1');
— это неправильное решение. Пожалуйста, не делайте этого.
В вашем PHP коде может быть утечка памяти, и вы просто говорите серверу использовать все доступные ресурсы. Таким образом, вы не решаете проблему. Если вы будете мониторить ваш сервер, вы увидите, что память, скорее всего, используется в основном объеме, и данные начинают перемещаться на диск.
Вам стоит попытаться найти проблемный участок кода и исправить его.
Правильный способ — отредактировать ваш файл php.ini
. Измените значение memory_limit
на желаемое.
Судя по вашему вопросу, вы превысили лимит в 128M
(что является значением по умолчанию), поэтому с вашим кодом что-то серьезно не так, так как он не должен потреблять столько памяти.
Если вы знаете, почему используется так много памяти и хотите это разрешить, установите memory_limit = 512M
или выше, и у вас всё должно заработать.
Память в PHP можно настраивать как постоянно, так и временно.
Постоянная настройка
Чтобы изменить лимит памяти PHP на постоянной основе, есть два способа.
Если у вас есть доступ к файлу
php.ini
, вы можете отредактировать значение дляmemory_limit
, установив его на желаемое значение.Если доступа к файлу
php.ini
у вас нет (и ваш хостинг это позволяет), вы можете переопределить лимит памяти через файл.htaccess
. Для этого добавьте строкуphp_value memory_limit 128M
(или любое другое желаемое значение).
Временная настройка
Вы также можете временно изменить лимит памяти в любом PHP файле. Для этого просто добавьте следующую строку кода: ini_set('memory_limit', '128M');
(или любое другое значение, которое вам нужно). Вы можете убрать лимит памяти, установив значение "-1" (хотя ограничения системы или инстанса по-прежнему могут действовать).
В PHP-сценариях довольно легко возникнуть утечкам памяти, особенно если вы используете абстракции, такие как ORM. Попробуйте использовать Xdebug для профилирования вашего скрипта и выясните, куда уходит вся эта память.
При добавлении 22,5 миллиона записей в массив с помощью array_push
я постоянно получал фатальные ошибки "исчерпанная память" примерно на 20 миллионах записей, несмотря на то, что в php.ini
был установлен лимит памяти в 4G
. Чтобы это исправить, я добавил следующую строку в начало файла:
$old = ini_set('memory_limit', '8192M');
Теперь всё работает нормально. Я не знаю, есть ли у PHP утечка памяти. Это не моя работа, и меня это не интересует. Я просто должен завершить свою задачу, и данный подход сработал.
Программа очень проста:
$fh = fopen($myfile);
while (!feof($fh)) {
array_push($file, stripslashes(fgets($fh)));
}
fclose($fh);
Фатальная ошибка указывала на третью строку, пока я не увеличил лимит памяти, что устранило проблему.
Как создать утечку памяти в Java?
Как вывести ошибки PHP на экран?
UTF-8 на всех уровнях!
Функции startsWith() и endsWith() в PHP
Что такое потокобезопасность и непотокобезопасность в PHP?