Fatal Error: Allowed Memory Size of 134217728 Bytes Exhausted (CodeIgniter + XML-RPC)
我有一堆客户销售点(POS)系统,它定期将新的销售数据发送到一个集中数据库,该数据库将数据存储到一个大数据库中以生成报告。
客户端POS基于PHPPOS,我已经实现了一个使用标准XML-RPC库将销售数据发送到服务的模块。服务器系统基于CodeIgniter构建,并使用XML-RPC和XML-RPCS库作为Web服务组件。每当我发送大量销售数据(销售表中只有50行,以及sales_items中与销售中每个项目相关的各行)时,我会收到以下错误:
1 | Fatal error: Allowed memory size of 134217728 bytes exhausted (tried to allocate 54 bytes) |
128M是
至于我采取的步骤,我已经尝试禁用服务器端的所有处理,并且已经操纵它以返回固定响应而不管输入如何。但是,我认为问题在于实际发送数据。我甚至尝试禁用PHP的最大脚本执行时间,但它仍然出错。
通过
您的PHP代码可能在某处出现内存泄漏,并且您告诉服务器只使用它想要的所有内存。你根本不会解决这个问题。如果您监视服务器,您将看到它现在可能正在耗尽大部分RAM甚至交换到磁盘。
您可能应该尝试在代码中跟踪有问题的代码并进行修复。
正确的方法是编辑
将
从您的问题来看,
如果你知道它为什么需要这么多,你想让它设置
PHP的内存分配可以永久调整,也可以暂时调整。
永久性
您可以通过两种方式永久更改PHP内存分配。
如果您有权访问
如果您无权访问
临时
您可以在PHP文件中动态调整内存分配。你只需要代码
在PHP脚本中很容易出现内存泄漏 - 尤其是在使用抽象时,例如ORM。尝试使用Xdebug来分析您的脚本并找出所有内存的去向。
当使用array_push向数组中添加2250万条记录时,我使用
1 |
在文件的顶部。现在一切正常。我不知道PHP是否有内存泄漏。那不是我的工作,也不关心。我只需要完成我的工作,这很有效。
该程序非常简单:
1 2 3 4 5 | $fh = fopen($myfile); while (!feof($fh)) { array_push($file, stripslashes(fgets($fh))); } fclose($fh); |
致命错误指向第3行,直到我提高内存限制为止
消除了错误。
即使在
通过改变它:
1 | memory_limit=4G |
对此:
1 | memory_limit=4096M |
这解决了PHP 7中的问题。
当你看到上面的错误 - 特别是如果
1 2 3 4 | function exhaustYourBytes() { return exhaustYourBytes(); } |
启用这两行后,它开始工作:
1 2 3 4 5 6 7 8 9 10 11 | ; 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 |
您可以通过更改fastcgi / fpm上的
1 | $vim /etc/php5/fpm/php.ini |
更改内存,如128到512,见下文
1 2 3 | ; Maximum amount of memory a script may consume (128 MB) ; http://php.net/memory-limit memory_limit = 128M |
至
1 2 3 | ; Maximum amount of memory a script may consume (128 MB) ; http://php.net/memory-limit memory_limit = 512M |
您网站的根目录:
1 |
对于Drupal用户,这个Chris Lane的答案是:
1 |
有效,但我们需要在开幕后才提出来
1 | <?php |
标记在站点根目录的index.php文件中。
在Drupal 7中,您可以修改站点/默认文件夹中的settings.php文件中的内存限制。在第260行附近,你会看到:
1 |
即使你的php.ini设置足够高,如果没有在你的Drupal settings.php文件中设置,你将无法消耗超过128 MB。
更改php.ini文件中的内存限制并重新启动Apache。重启后,运行phpinfo();从任何PHP文件中执行
1 | memory_limit = -1 |
内存限制-1表示没有设置内存限制。它现在处于最大值。
如果您的代码的一部分可以使用大量内存,而不是更改
1 2 3 4 |
崩溃页面?
(当MySQL必须查询大行时会发生这种情况。默认情况下,
在增加
1 2 3 4 5 | # free -m total used free shared buffers cached Mem: 64457 63791 666 0 1118 18273 -/+ buffers/cache: 44398 20058 Swap: 1021 0 1021 |
在这里我增加了它,如下所示,然后执行
1 2 | # grep memory_limit /etc/php.ini memory_limit = 512M |
PHP 5.3+允许您通过在
只需创建上述文件并在其中键入以下行:
1 | memory_limit = 64M |
某些cPanel主机仅接受此方法。
对于那些摸不着头脑,找出原因,这个小函数应该导致内存泄漏的人,有时会因为一点点错误,一个函数开始递归地调用自己。
例如,一个代理类,它与要代理它的对象的函数具有相同的名称。
1 2 3 4 5 6 7 8 9 | class Proxy { private $actualObject; public function doSomething() { return $this->actualObjec->doSomething(); } } |
有时你可能会忘记带上那个小的actualObjec成员,因为代理实际上有那个
我在以前工作的数据集上运行时遇到了以下错误。
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,157&nbsp; MB。
事实证明,我在一段时间内一次看了50分钟的视频,这让事情搞得一团糟。这是专家在没有考虑的情况下纠正的那种解决办法,但对于我这样的人来说,值得记住。
如果您正在运行WHM驱动的VPS(虚拟专用服务器),您可能会发现您没有直接编辑PHP.INI的权限;系统必须这样做。在WHM主机控制面板中,转到Service Configuration&rarr; PHP配置编辑器并修改
我发现在实际处理的文件中包含或要求
因此,如果包含页眉和页脚,只需在包含标题之前包含所有功能文件。
像这样运行脚本(例如cron case):
正确的方法:
此错误有时是由PHP代码中的错误引起的,该错误会导致涉及异常处理和可能的其他操作的递归。不幸的是,我无法创造一个小例子。
在这些情况下,已经多次发生过这种情况,
通过添加减少允许的分配大小
1 |
在代码开头附近,您应该能够防止致命错误。
然后你可能会留下一个终止??的程序,但仍然很难调试。
此时插入
BreakLoop的定义如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 | function BreakLoop($MaxRepetitions=500,$LoopSite="unspecified") { static $Sites=[]; if (!@$Sites[$LoopSite] || !$MaxRepetitions) $Sites[$LoopSite]=['n'=>0, 'if'=>0]; if (!$MaxRepetitions) return; if (++$Sites[$LoopSite]['n'] >= $MaxRepetitions) { $S=debug_backtrace(); // array_reverse $info=$S[0]; $File=$info['file']; $Line=$info['line']; exit("*** Loop for site $LoopSite was interrupted after $MaxRepetitions repetitions. In file $File at line $Line."); } } // BreakLoop |
$ LoopSite参数可以是代码中函数的名称。这不是必需的,因为您将获得的错误消息将指向包含BreakLoop()调用的行。
就我而言,这是函数编写方式的一个简短问题。通过为函数的输入变量赋值,可能会导致内存泄漏,例如:
1 2 3 4 5 6 7 8 9 10 | /** * Memory leak function that illustrates unintentional bad code * @param $variable - input function that will be assigned a new value * @return null **/ function doSomehting($variable){ $variable = 'set value'; // Or $variable .= 'set value'; } |
使用
有时在循环内部实现
只需在网页顶部添加
您可以根据需要在-1,
当我从代码中删除以下行时,一切正常!
1 2 3 | set_include_path(get_include_path() . get_include_path() . '/phpseclib'); include_once('Net/SSH2.php'); include_once('Net/SFTP.php'); |
这些行包含在我运行的每个文件中。一个接一个地运行文件,一切正常,但是当一起运行所有文件时,我遇到了内存泄漏问题。不知何故,"include_once"不包括一次,或者我做错了什么......