Неустранимая ошибка: допустимый объем памяти 134217728 байт исчерпан (CodeIgniter + XML-RPC)

525

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

Клиентский POS основан на PHPPOS, и я внедрил модуль, который использует стандартную библиотеку XML-RPC для отправки данных о продажах в службу. Серверная система построена на CodeIgniter и использует библиотеки XML-RPC и XML-RPCS для компонента webservice. Всякий раз, когда я отправляю много данных о продажах (всего лишь 50 строк из таблицы продаж и отдельных строк из sales_items, относящихся к каждому элементу в продаже), я получаю следующую ошибку:

Fatal error: Allowed memory size of 134217728 bytes exhausted (tried to allocate 54 bytes)

128M - значение по умолчанию в php.ini, но я предполагаю, что это огромное количество сломать. На самом деле, я даже попытался установить это значение на 1024 М, и все, что он делает, занимает больше времени для выхода из системы.

Что касается шагов, которые я предпринял, я попытался отключить всю обработку на стороне сервера и сфальсифицировал его, чтобы возвращать консервированный ответ независимо от ввода. Однако я считаю, что проблема заключается в фактической отправке данных. Я даже попытался отключить максимальное время выполнения script для PHP, и он все еще не работает.

  • 5
    Я немного запутался ... где происходит ошибка - на клиенте или сервере? И на каком этапе ... отправка клиента, получение сервера, обработка сервера, отправка сервера, получение клиента или обработка клиента?
  • 0
    Как / где вы устанавливаете memory_limit на 1024M?
Показать ещё 5 комментариев
Теги:
codeigniter
memory
xml-rpc
memory-limit

25 ответов

652

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

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

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

  • 155
    @ Джефф, наверное, ты прав в 95% случаев. Однако бывают случаи, когда вам действительно нужно больше памяти. Например, предположим, что ваше приложение загружает огромный объем данных в память для обработки (например, спецификация с 15k компонентами). Это не всегда тот случай, когда код содержит ошибки, иногда вам просто нужно немного больше памяти (например, 256M вместо 128M). Однако я согласен, что установка его в -1 ужасно плохо. Но настройка предела памяти для разумных ситуаций во время выполнения вполне приемлема imho.
  • 18
    @ Pyrite Да, вы правы, что иногда процессу требуется больше памяти, но вы должны увеличить предел памяти до некоторого логического объема, например, 256 МБ, как вы сказали, или 512 МБ, почему бы не НО-не -1;)
Показать ещё 6 комментариев
202

ini_set('memory_limit', '-1'); отменяет установленный по умолчанию предел памяти PHP.

  • 0
    где можно это изменить ?! Я нахожу эту строку только в php.ini
  • 4
    Почему -1 в ini_set работает, хотя?
Показать ещё 17 комментариев
106

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

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

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

  • 7
    Честно говоря, если вы кешируете какие-то серьезные объемы данных, это правильный ответ. 128M недостаточно для определенных сценариев. 512M или 1024M часто будет достаточно, но вы должны решать в каждом конкретном случае.
  • 2
    Да, однако старайтесь избегать огромного использования памяти, если число пользователей будет больше
Показать ещё 2 комментария
89

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

Постоянно

Вы можете навсегда изменить распределение памяти PHP двумя способами.

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

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

Временный

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

  • 2
    Спасибо, я не думал проверять, установил ли кто-то значение в .htaccess, которое переопределяло php.ini, и я не мог понять, почему +1
57

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

  • 1
    Я пойду попробую Xdebug. Я никогда не использовал его раньше, поэтому мне придется прочитать об этом. Спасибо за ответ! Надеюсь, я скоро найду ответ на этот вопрос ...
  • 31
    Помните, что PHP использует подсчет ссылок для управления памятью. Поэтому, если у вас есть циклические ссылки или глобальные переменные, эти объекты не будут переработаны. Это обычно корень утечек памяти в PHP.
Показать ещё 4 комментария
50

Добавляя 22,5 миллиона записей в массив с помощью array_push, я продолжал получать фатальные ошибки "исчерпана память" - около 20 миллионов записей, используя 4G в качестве предела памяти в php.ini. Чтобы исправить это я добавил выражение

$old = ini_set('memory_limit', '8192M'); 

в верхней части файла. Теперь все работает нормально. Я не знаю, есть ли у php утечка памяти, это не моя работа, и мне все равно. Я просто должен сделать свою работу, и это сработало.

Программа очень проста:

$fh = fopen($myfile);
while (!feof($fh)) {
      array_push($file, stripslashes(fgets($fh)));
}  
fclose($fh);

Неустранимая ошибка указывает на строку 3, пока я не увеличил предел памяти, что устранило ошибку.

  • 10
    Вы имеете в виду ini_set('memory_limit', '8192M'); ?
  • 1
    лучшее решение ! это сработало для меня!
Показать ещё 2 комментария
41

Я продолжал получать эту ошибку, даже когда memory_limit установлен в php.ini, и значение правильно phpinfo() с помощью phpinfo().

Изменяя это от этого:

memory_limit=4G

К этому:

memory_limit=4096M

Это исправило проблему в PHP 7.

19

Когда вы видите вышеупомянутую ошибку, особенно если значение (tried to allocate __ bytes) является низким значением, это может быть индикатор бесконечного цикла, как функция, которая сама вызывает вызов:

function exhaustYourBytes()
{
    return exhaustYourBytes();
}
17

После включения этих двух строк.
Он начал работать

; Determines the size of the realpath cache to be used by PHP. This value should
; be increased on systems where PHP opens many files to reflect the quantity of
; the file operations performed.
; http://php.net/realpath-cache-size
realpath_cache_size = 16k

; Duration of time, in seconds for which to cache realpath information for a given
; file or directory. For systems with rarely changing files, consider increasing this
; value.
; http://php.net/realpath-cache-ttl
realpath_cache_ttl = 120

Изображение 737

  • 0
    Это не работает для меня
15

Вы можете исправить это, изменив memory_limit на fastcgi/fpm

$vim /etc/php5/fpm/php.ini

Изменить память, например, с 128 по 512, ниже

; Maximum amount of memory a script may consume (128MB)
; http://php.net/memory-limit
memory_limit = 128M

к

; Maximum amount of memory a script may consume (128MB)
; http://php.net/memory-limit
memory_limit = 512M
13

Корневой каталог вашего сайта:

ini_set('memory_limit', '1024M');
  • 1
    это сработало для меня. люблю одну линию решений. +1 для простоты
10

В Drupal 7 вы можете изменить ограничение памяти в файле settings.php, расположенном в папке/папке по умолчанию. В строке 260 вы увидите следующее:

ini_set('memory_limit', '128M');

Даже если ваши настройки php.ini достаточно высоки, вы не сможете потреблять более 128 МБ, если это не задано в файле настроек Drupal settings.php.

  • 1
    В Drupal7 нет такой строки кода в settings.php
  • 0
    В файле settings.php также нет строки для drupal 6
9

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

$limit = ini_get('memory_limit');
ini_set('memory_limit', -1);
// ... do heavy stuff
ini_set('memory_limit', $limit);
9

Для пользователей Drupal этот ответ Криса Лейна:

ini_set('memory_limit', '-1');

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

<?php

в файле index.php в корневом каталоге вашего сайта.

6

CRASH страница? Изображение 738

(Это происходит, когда MySQL должен запрашивать большие строки, по умолчанию для momory_limit установлено значение small, что было более безопасно для оборудования)

Вы можете проверить состояние вашей системы в существующей памяти, прежде чем увеличивать php.ini

# free -m
             total       used       free     shared    buffers     cached
Mem:         64457      63791        666          0       1118      18273
-/+ buffers/cache:      44398      20058
Swap:         1021          0       1021

Здесь я увеличил его следующим образом, а затем service httpd restart чтобы исправить проблему с CRASH-страницей.

# grep memory_limit /etc/php.ini
memory_limit = 512M
6

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

Например, прокси-класс, который имеет одно и то же имя для функции объекта, который будет проксировать его.

class Proxy {

    private $actualObject;

    public function doSomething() {

        return $this->actualObjec->doSomething();
    }
}   

Иногда вы можете забыть принести этот маленький член actualObjec, и поскольку у Proxy действительно есть метод doSomething, PHP не даст вам никаких ошибок и для большого класса, он может быть скрыт от глаз на пару минут до узнайте, почему он просачивает память.

  • 0
    И еще один совет: вы можете поместить die('here') в свой код и переместить этот оператор, чтобы увидеть, где начинается рекурсия.
6

PHP 5.3+ позволяет вам изменить ограничение памяти, поместив файл .user.ini в папку public_html. Просто создайте указанный выше файл и введите в него следующую строку:

memory_limit = 64M

Некоторые хосты cPanel принимают этот метод только.

4

Измените ограничение памяти из файла php.ini и перезапустите apache. После перезапуска запустите phpinfo(); функция из любого php файла для подтверждения изменения memory_limit.

memory_limit = -1

ограничение памяти -1 означает, что ограничение памяти не установлено, теперь оно максимально.

3

У меня была ошибка ниже при работе на наборе данных меньше, чем раньше.

Fatal error: Allowed memory size of 134217728 bytes exhausted (tried to allocate 4096 bytes) in C:\\workspace\image_management.php on line 173

Поскольку поиск ошибки привел меня сюда, я подумал, что я бы сказал, что это не всегда технические решения выше, а что-то более простое. В моем случае это был Firefox. Прежде чем я запустил программу, он уже использовал 1,157M.
Оказывается, я смотрел 50-минутный видеоролик за раз в течение нескольких дней, и это все испортило. Это своего рода исправить, что эксперты исправляют, даже не думая об этом, но для подобных мне это стоит задуматься.

3

Запуск script, как это (пример cron, например): php5 /pathToScript/info.php создает ту же ошибку.

Правильный способ: php5 -cli /pathToScript/info.php

3

Я считаю это полезным при включении или требовании:
dbconnection.php, _functions.php в файлах, которые фактически обрабатываются,
 вместо включения в заголовок. Который включен сам.

Итак, если ваш заголовок и нижний колонтитул включен, просто включите все ваши функциональные файлы перед включением заголовка.

3

Если вы используете VPS с виртуальным частным сервером (WHM), вы можете обнаружить, что у вас нет прав на редактирование PHP.INI напрямую; система должна это сделать. На панели управления хостом WHM откройте "Конфигурация службы" > "Редактор конфигурации PHP", измените memory_limit:

Изображение 739

0

Хатанин Çözümü burada verilmiş Hata Ayıklayıcı Çözemediğin bug kalmasın

-1

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

-4

не уверен, что этот ответ будет полезен, но когда я удалил следующие строки из моего кода, все работало нормально!

set_include_path(get_include_path() . get_include_path().'/phpseclib');

include_once ( 'Чистый/SSH2.php'); include_once ( 'Net/SFTP.php');

Эти строки были включены в каждый выполняемый файл, при работе с файлами один за другим все работало нормально, но при запуске всех файлов я получил проблему с утечкой памяти. Так или иначе "include_once" не включает в себя вещи один раз, или я делаю что-то неправильно.

  • 0
    set_include_path(get_include_path() . get_include_path().'/phpseclib'); Это добавит путь '/ phpseclib' один раз для каждого файла, который имеет строку ... так что он может добавить его много раз! Я бы предложил поместить его в файл настроек и include_once в него файл настроек.

Ещё вопросы

Сообщество Overcoder
Наверх
Меню