致命错误:允许的内存大小为134217728 Bytes Exhausted(CodeIgniter + XML-RPC)

Arc*_*ero 587 php memory codeigniter xml-rpc memory-limit

我有一堆客户销售点(POS)系统,它定期将新的销售数据发送到一个集中数据库,该数据库将数据存储到一个大数据库中以生成报告.

客户端POS基于PHPPOS,我已经实现了一个使用标准XML-RPC库将销售数据发送到服务的模块.服务器系统基于CodeIgniter构建,并使用XML-RPC和XML-RPCS库作为Web服务组件.每当我发送大量销售数据(销售表中只有50行,以及sales_items中与销售中每个项目相关的各行)时,我会收到以下错误:

Fatal error: Allowed memory size of 134217728 bytes exhausted (tried to allocate 54 bytes)
Run Code Online (Sandbox Code Playgroud)

128M是默认值php.ini,但我认为这是一个很大的数字.实际上,我甚至尝试将此值设置为1024M,而它所做的只是花费更长的时间来输出错误.

至于我采取的步骤,我已经尝试禁用服务器端的所有处理,并且已经操纵它以返回固定响应而不管输入如何.但是,我认为问题在于实际发送数据.我甚至尝试禁用PHP的最大脚本执行时间,但它仍然出错.

小智 685

改变memory_limitini_set('memory_limit', '-1');不是一个妥善的解决办法.请不要这样做.

您的PHP代码可能在某处出现内存泄漏,并且您告诉服务器只使用它想要的所有内存.你根本不会解决这个问题.如果您监视服务器,您将看到它现在可能正在耗尽大部分RAM甚至交换到磁盘.

您可能应该尝试在代码中跟踪有问题的代码并进行修复.

  • @Jeff你可能是95%的时间.但是,有时您确实需要更多内存.例如,假设您的应用正在将大量数据加载到内存中进行处理(例如,包含15k组件的物料清单).并不总是代码有问题,有时你只需要更多的内存(例如256M而不是128M).但是我同意将它设置为-1非常糟糕.但是,在运行时调整合理情况的内存限制是完全可以接受的. (166认同)
  • @pyrite是的,你是正确的,有时一个进程需要更多的内存,但你应该将内存限制增加到某个逻辑数量,如你所说的256MB或512MB为什么不但不是-1;) (21认同)
  • @jeff我完全同意,值"-1"在开发环境中仅用于测试目的**. (8认同)
  • 但是你如何追踪这种错误呢? (7认同)
  • @Pyrite在你为剩下的5%命名的情况下以块的形式读取数据并使用worker来处理它而不是使用更多的内存.此解决方案也将扩展,而您的建议将无法工作,除非您在数据增长的情况下随着时间的推移将越来越多的内存填充到您的服务器中. (4认同)
  • 以最常见的方式,当您尝试获取所有更多的php内存限制的数据时,ORM中的这种麻烦。例如,当您尝试生成每月报告时。 (2认同)

小智 208

ini_set('memory_limit', '-1');覆盖默认的PHP内存限制.

  • 遗憾的是,这得到了如此多的赞成.当人们需要更多内存时,使用php.ini编辑或ini_set将其设置为准确值是一个非常有效的解决方案.将它设置为无限是一个危险的黑客:( (120认同)
  • @ user1767586然后将其设置为合理的值.您可以通过将脚本设置为1024M来防止脚本抛出错误.如果这个答案说的是ini_set('memory_limit','1024M'); 你可以复制粘贴那个并且没问题.通过将其设置为-1,您可以设置一个消耗所有内存的脚本.特别是如果你这样做的话.将"危险"放在引号中并不会使它变得不那么危险.你真的可以管你的主机服务器.也许开始破坏数据.我不知道,也许会失去你的工作?对我来说听起来很危险.:| (23认同)
  • @williamcarswell; `-1`是PHP在此上下文中理解为*unlimited*的值. (15认同)
  • @ArseniuszŁozicki - 它也会消耗服务器*不能*备用的资源. (7认同)
  • 为什么ini_set中的-1工作呢? (5认同)
  • 很遗憾看到+161票和-3票的答案是一样的:( (3认同)
  • 在某些情况下,你绝对需要完成某些事情,然后将其改回合理的设置,这确实有帮助. (2认同)
  • 在充分尊重的情况下,这个答案应该被遗忘.该解决方案"修复"了一个问题,但引入了许多其他问题.这就像交换了你所获得的一个魔鬼以换取数十个魔鬼.正如已经提出的那样,(1)在```php.ini```中的```memory_limit```中增加全局PHP内存可用性和/或(2)诊断内存泄漏. (2认同)
  • 这是一个非常糟糕的主意 (2认同)

Bas*_*sav 125

正确的方法是编辑您的php.ini文件.memory_limit根据您的愿望值编辑.

从您的问题来看,128M(已经超出了默认限制),因此您的代码存在严重问题,因为它不应该占用太多.

如果你知道它为什么需要这么多而且你想允许它设置memory_limit = 512M或更高,你应该是好的.

  • 老实说,如果您缓存了大量数据,这是正确的答案.对于某些脚本,128M是不够的.512M或1024M通常就足够了,但你必须根据具体情况来决定. (7认同)
  • 但是,如果用户数量会更多,那么尝试避免大量使用内存 (2认同)
  • 内存限制 = -1 ; 在 php.ini 中设置 (2认同)
  • @YumYumYum删除memory_limit,如果你以其他方式监视内存使用情况,你只需要它.如果它在某个时刻以某种方式占用大量内存,操作系统将终止该进程. (2认同)

小智 94

PHP的内存分配可以永久调整,也可以暂时调整.

永久性

您可以通过两种方式永久更改PHP内存分配.

如果您有权访问您的php.ini文件,则可以根据需要编辑memory_limit值.

如果您无权访问您的php.ini文件(并且您的webhost允许),您可以通过.htaccess文件覆盖内存分配.添加php_value memory_limit 128M(或任何您想要的分配).

临时

您可以在PHP文件中动态调整内存分配.你只需要代码ini_set('memory_limit', '128M');(或任何你想要的分配).您可以通过将值设置为"-1"来删除内存限制(尽管可能仍适用机器或实例限制).

  • 谢谢你我没想过要检查是否有人在.htaccess中设置了覆盖php.ini的值,我无法弄清楚为什么+1 (2认同)

tro*_*skn 60

在PHP脚本中很容易出现内存泄漏 - 尤其是在使用抽象时,例如ORM.尝试使用Xdebug来分析您的脚本并找出所有内存的去向.

  • 请记住,PHP使用引用计数来管理内存.因此,如果您有循环引用或全局变量,那么这些对象将不会被回收.这通常是PHP内存泄漏的根源. (33认同)
  • 我去试试Xdebug。我以前从未使用过它,所以我必须阅读它。谢谢您的回复!希望我能尽快找到这个问题的答案...... (2认同)

Jam*_*D-0 55

当使用array_push向数组中添加2250万条记录时,我使用4G作为php.ini中的内存限制,在大约20M记录中不断出现"内存耗尽"致命错误.为了解决这个问题,我添加了声明

$old = ini_set('memory_limit', '8192M');
Run Code Online (Sandbox Code Playgroud)

在文件的顶部.现在一切正常.我不知道php是否有内存泄漏,这不是我的工作,也不关心.我只需要完成我的工作,这很有效.

该程序非常简单:

$fh = fopen($myfile);
while (!feof($fh)) {
    array_push($file, stripslashes(fgets($fh)));
}
fclose($fh);
Run Code Online (Sandbox Code Playgroud)

致命错误指向第3行,直到我提高了内存限制,从而消除了错误.

  • 你的意思是`ini_set('memory_limit','8192M');`? (10认同)
  • 花时间去优化诸如此类的脚本是多么的奢侈。或研究和比较并学习ETL工具或类似工具。在现实世界中,我们提高了内存余量,执行该操作,然后继续前进。 (2认同)
  • 2200 万条记录☠️ (2认同)

Dan*_*ett 45

我一直收到这个错误,即使memory_limit设置为php.ini,并且正确读出的值phpinfo().

通过改变它:

memory_limit=4G
Run Code Online (Sandbox Code Playgroud)

对此:

memory_limit=4096M
Run Code Online (Sandbox Code Playgroud)

这解决了PHP 7中的问题.


Kri*_*ite 23

当你看到上面的错误 - 特别是如果它(tried to allocate __ bytes)是一个低值时,这可能是一个无限循环的指示器,就像一个无法自行调用自身的函数:

function exhaustYourBytes()
{
    return exhaustYourBytes();
}
Run Code Online (Sandbox Code Playgroud)


小智 19

启用这两行后.
它开始工作了

; 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
Run Code Online (Sandbox Code Playgroud)


小智 19

您可以通过更改fastcgi/fpm上的memory_limit来正确解决此问题

$vim /etc/php5/fpm/php.ini
Run Code Online (Sandbox Code Playgroud)

更改内存,如128到512,见下文

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

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


Gau*_*g P 17

您网站的根目录: -

ini_set('memory_limit', '1024M');
Run Code Online (Sandbox Code Playgroud)

  • 这对我有用。喜欢单线解决方案。为简单起见+1 (2认同)

sig*_*i13 13

对于Drupal用户,这个Chris Lane的答案是:

ini_set('memory_limit', '-1');
Run Code Online (Sandbox Code Playgroud)

有效,但我们需要在开幕后才提出来

<?php
Run Code Online (Sandbox Code Playgroud)

标记在站点根目录的index.php文件中.


小智 12

在Drupal 7中,您可以修改站点/默认文件夹中的settings.php文件中的内存限制.在第260行附近,你会看到:

ini_set('memory_limit', '128M');
Run Code Online (Sandbox Code Playgroud)

即使你的php.ini设置足够高,你将无法如果这是不是在你的Drupal的settings.php文件中设置消耗比128MB以上.


小智 12

如果您的代码的一部分可以使用大量内存,而不是更改文件中的memory_limitphp.ini,则可以memory_limit在该部分运行之前删除它,然后在之后替换它.

$limit = ini_get('memory_limit');
ini_set('memory_limit', -1);
// ... do heavy stuff
ini_set('memory_limit', $limit);
Run Code Online (Sandbox Code Playgroud)


Has*_*mal 12

php.ini文件更改内存限制并重新启动apache.重新启动后运行phpinfo(); 函数来自任何php文件,用于memory_limit更改确认.

memory_limit = -1
Run Code Online (Sandbox Code Playgroud)

内存限制-1表示没有内存限制设置它现在是最大值.


小智 11

只需ini_set('memory_limit', '-1');在网页顶部添加一行即可。

您可以根据需要在 -1、to16M等位置设置内存。

  • 这似乎与许多现有答案说的一样。最好仅在新材料提供新颖内容时才为流行问题添加答案。 (10认同)

小智 7

PHP 5.3+允许您通过在.user.ini文件public_html夹中放置文件来更改内存限制.只需创建上述文件并在其中键入以下行:

memory_limit = 64M
Run Code Online (Sandbox Code Playgroud)

某些cPanel主机仅接受此方法.


小智 7

CRASH页面? 在此输入图像描述

(当MySQL必须查询大行时会发生这种情况,默认情况下,momory_limit设置为较小,这对硬件来说更安全)

在增加之前,您可以检查系统的现有内存状态 memory_limit

# free -m
             total       used       free     shared    buffers     cached
Mem:         64457      63791        666          0       1118      18273
-/+ buffers/cache:      44398      20058
Swap:         1021          0       1021
Run Code Online (Sandbox Code Playgroud)

在这里我增加了它,然后php.ini修复CRASH页面问题.

# grep memory_limit /etc/php.ini
memory_limit = 512M
Run Code Online (Sandbox Code Playgroud)


Dra*_*ire 7

就我的 mac(Catalina - Xampp)而言,没有加载文件,所以我必须先执行此操作。

sudo cp /etc/php.ini.default /etc/php.ini
sudo nano /etc/php.ini
Run Code Online (Sandbox Code Playgroud)

然后改变memory_limit = 512M

然后重新启动 Apache 并检查文件是否已加载

php -i | grep php.ini
Run Code Online (Sandbox Code Playgroud)

结果是

Configuration File (php.ini) Path => /etc
Loaded Configuration File => /etc/php.ini
Run Code Online (Sandbox Code Playgroud)

最后检查

php -r "echo ini_get('memory_limit').PHP_EOL;"
Run Code Online (Sandbox Code Playgroud)


mad*_*adz 6

对于那些为了找到原因而在地球上找到原因的人来说,这个小函数应该会导致内存泄漏,有时会出现一点点错误,函数会以递归的方式开始递归调用自身.

例如,对于要代理它的对象的函数具有相同名称的代理类.

class Proxy {

    private $actualObject;

    public function doSomething() {

        return $this->actualObjec->doSomething();
    }
}
Run Code Online (Sandbox Code Playgroud)

有时你可能会忘记带上那个小的actualObjec成员,因为Proxy实际上有doSomething方法,PHP不会给你任何错误,对于一个大类,它可以隐藏在眼睛里几分钟,找出原因它正在泄漏记忆.


M61*_*can 6

在比以前工作的数据集更小的数据集上运行时出现以下错误。

致命错误:第 173 行 C:\workspace\image_management.php 中允许的内存大小为 134217728 字节(试图分配 4096 字节)

由于寻找故障将我带到这里,我想我会提到它并不总是之前答案中的技术解决方案,而是更简单的东西。就我而言,它是 Firefox。在我运行该程序之前,它已经使用了 1,157 MB。

事实证明,我在几天内一次观看了一段 50 分钟的视频,这把事情搞砸了。这是一种专家甚至没有考虑就纠正的修复方法,但对于我这样的人来说,值得牢记。