8

Фатальная ошибка: исчерпано разрешённое объём памяти 134217728 байт

5

Проблема с исчерпанием памяти при отправке данных о продажах из системы 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 ответ(ов)

8

Изменение memory_limit с помощью ini_set('memory_limit', '-1'); — это неправильное решение. Пожалуйста, не делайте этого.

В вашем PHP коде может быть утечка памяти, и вы просто говорите серверу использовать все доступные ресурсы. Таким образом, вы не решаете проблему. Если вы будете мониторить ваш сервер, вы увидите, что память, скорее всего, используется в основном объеме, и данные начинают перемещаться на диск.

Вам стоит попытаться найти проблемный участок кода и исправить его.

1

Правильный способ — отредактировать ваш файл php.ini. Измените значение memory_limit на желаемое.

Судя по вашему вопросу, вы превысили лимит в 128M (что является значением по умолчанию), поэтому с вашим кодом что-то серьезно не так, так как он не должен потреблять столько памяти.

Если вы знаете, почему используется так много памяти и хотите это разрешить, установите memory_limit = 512M или выше, и у вас всё должно заработать.

1

Память в PHP можно настраивать как постоянно, так и временно.

Постоянная настройка

Чтобы изменить лимит памяти PHP на постоянной основе, есть два способа.

  1. Если у вас есть доступ к файлу php.ini, вы можете отредактировать значение для memory_limit, установив его на желаемое значение.

  2. Если доступа к файлу php.ini у вас нет (и ваш хостинг это позволяет), вы можете переопределить лимит памяти через файл .htaccess. Для этого добавьте строку php_value memory_limit 128M (или любое другое желаемое значение).

Временная настройка

Вы также можете временно изменить лимит памяти в любом PHP файле. Для этого просто добавьте следующую строку кода: ini_set('memory_limit', '128M'); (или любое другое значение, которое вам нужно). Вы можете убрать лимит памяти, установив значение "-1" (хотя ограничения системы или инстанса по-прежнему могут действовать).

0

В PHP-сценариях довольно легко возникнуть утечкам памяти, особенно если вы используете абстракции, такие как ORM. Попробуйте использовать Xdebug для профилирования вашего скрипта и выясните, куда уходит вся эта память.

0

При добавлении 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);

Фатальная ошибка указывала на третью строку, пока я не увеличил лимит памяти, что устранило проблему.

Чтобы ответить на вопрос, пожалуйста, войдите или зарегистрируйтесь