是什么导致PHP中“无法为池分配内存”?


133

我偶尔会遇到服务器的内存分配限制,尤其是对于像Wordpress这样a肿的应用程序,但是却从未遇到过“无法为池分配内存”和跟踪任何信息的麻烦。

有人知道这意味着什么吗?我尝试增加memory_limit失败。我也没有对该应用程序进行任何重大更改。有一天没有问题,第二天我遇到了这个错误。

Answers:


90

可能与APC有关。

对于有此问题的人,请指定您的.ini设置。特别是您的apc.mmap_file_mask设置。

对于文件支持的mmap,应将其设置为:

apc.mmap_file_mask=/tmp/apc.XXXXXX

要直接从/ dev / zero映射,请使用:

apc.mmap_file_mask=/dev/zero

对于兼容POSIX的共享内存支持的mmap,请使用:

apc.mmap_file_mask=/apc.shm.XXXXXX

谢谢!那正是我一直在寻找的链接。感谢帮助!
jonathanatx

2
我发现这些更改无法解决问题,因为对链接线程的评论也记录在案...
Jonathan Day


2
就我而言,我必须从文件支持更改为POSIX兼容,以消除错误。
Attila Fulop 2012年

4
我不知所措,无法理解此答案如何解决问题。当file_mask不是这些值之一时,会发生错误吗?如果我具有这些值之一,并且出现错误,是否需要将其切换为其他值?哪一个?
杰夫

125

使用TTL为0表示APC 在内存用尽时将刷新所有缓存。该错误不再出现,但是使APC的效率大大降低。这是没有风险,没有麻烦的“我不想做我的工作”的决定。APC并非旨在以这种方式使用。您应该选择足够高的TTL,以便访问最多的页面不会过期。最好是提供足够的内存,以便APC不需要刷新缓存。

只需阅读手册即可了解如何使用ttl:http//www.php.net/manual/en/apc.configuration.php#ini.apc.ttl

解决方案是增加分配给APC的内存。通过增加apc.shm_size来执行此操作。

如果将APC编译为使用共享段内存,则将受到操作系统的限制。输入以下命令以查看每个段的系统限制:

sysctl -a | grep -E "shmall|shmmax"

要分配更多的内存,您必须使用参数apc.shm_segments增加段数。

如果APC使用mmap内存,则没有限制。内存量仍由同一选项apc.shm_size定义。

如果服务器上没有足够的内存,请使用过滤器选项以防止缓存访问频率较低的php文件。

但切勿使用TTL为0。

正如c33s所说,使用apc.php检查您的配置。将文件从apc包复制到Web文件夹,然后将浏览器指向它。您将看到真正分配了什么以及如何使用它。这些图形必须在小时后保持稳定,如果它们在每次刷新时都发生完全更改,则表示您的设置有误(APC正在刷新所有内容)。分配的内存比APC实际用作安全余量的内存多20%,并定期检查。

缺省情况下,仅允许32MB的值太低了。PHP是在服务器为64MB且大多数脚本每页使用一个php文件时设计的。如今,像Magento这样的解决方案需要超过1万个文件(在APC中约为60Mb)。您应该留出足够的内存,以便大多数php文件始终被缓存。这不是浪费,将操作码保留在ram中比将相应的原始php保留在文件缓存中更为有效。如今,我们可以找到具有24Gb内存的专用服务器,每月低至80美元,因此,请毫不犹豫地允许AGB占用几GB。我在托管5个Magento商店和约40个wordpress网站的服务器上将24 GB中的2 GB用于APC使用1.2 GB。对于Magento安装,计数为64MB,对于带有某些插件的Wordpress,计数为40MB。

另外,如果您在同一服务器上有开发网站。从缓存中排除它们。


2
这个!我正在运行Wordpress,而32M仅仅是不够的。现已增加到64M。检查apc.php人!
戴夫·德拉格2012年

好答案!+1谢谢。
Kostanos 2013年

要增加到64M,您需要添加apc.shm_size = 64而不是apc.shm_size = 64M(我看到的大多数示例最后都有一个M)在我的apc版本(v3.1.3p1)上不起作用
帕特里克·忘记

1
您假定您将有很多缓存文件,它们在缓存中的存留时间比TTL长。c33s具有重要意义。如果所有内容最近都被访问过(假设您有70%的缓存可以随时随地访问,并且出现了很大的高峰,一次又添加了很多额外的不频繁文件),那么您将得到错误抛出TTL秒。缓存已满,您告诉APC它不应该清除这些条目,因此会抱怨。如果您有5个小时的TTL,则最终将有5个小时的错误等待这些不常见的文件过期。
马修·科尔布

@MatthewKolb:您不应允许缓存的文件数量超出APC在其内存中可以容纳的数量。使用过滤器来防止不经常访问的文件被缓存。
bokan 2014年

36

我的解决方案:

  • apc.ttl = 0
  • apc.shm_size =您想要的任何东西

编辑开始

警告!

@bokan指示我应该在此处添加警告。

如果ttl为0,则意味着可以立即清除每个缓存的项目。因此,如果您的缓存大小较小(例如2mb),并且ttl为0,则这将使apc无法使用,因为缓存中的数据总是会被覆盖。

降低ttl意味着仅高速缓存无法充满,只能使用无法替换的项目。

因此您必须在ttl和缓存大小之间选择一个良好的平衡。

在我的情况下,我的缓存大小为1gb,因此对我来说绰绰有余。

编辑结束

在centos 5上使用php 5.2.17遇到了相同的问题,并注意到,如果缓存大小较小并且ttl参数为“ high”(例如7200),同时要缓存大量php文件,则缓存会很快填充并且apc找不到可以删除的任何内容,因为缓存中的所有文件仍然适合ttl。

增加内存大小只是一部分解决方案,如果缓存已满并且所有文件都在ttl内,则仍然会出现此错误。

所以我的解决方案是将ttl设置为0,以便apc填满缓存,并且apc总是有可能为新数据清除一些内存。

希望能有所帮助

编辑:另请参见:http : //pecl.php.net/bugs/bug.php?id=16966

下载http://pecl.php.net/get/APC解压缩并运行apc.php,那里有一个很好的图表,说明缓存的使用情况


2
谢谢,这确实有帮助。我每秒收到十几个“无法分配内存”错误。我将缓存大小增加了一倍(从32到64 MB),并将ttl降至0。这完全消除了这些错误。
nicktacular 2011年

1
这是我们服务器上的修复程序。
贾斯汀

1
这似乎也为我解决了这个问题。
anisoptera

1
使用ZWAMP似乎也可以解决问题。谢谢。
WernerCD 2011年

10
这不是解决方案!该错误消失了,但是APC几乎被禁用了。每当内存已满时,它将刷新所有缓存。只需阅读Brideau给我们的手册即可。php.net/manual/en/apc.configuration.php#ini.apc.ttl。
博坎,2012年

7

运行apc.php脚本是了解问题所在的关键,IMO。这有助于我们正确调整缓存大小,目前看来已解决了该问题。


1
正如c33s所说:下载pecl.php.net/get/APC解压缩文件并运行apc.php,那里有一个很好的图表,显示您的缓存使用情况
bokan,2012年

4

对于像我这样的新手,这些资源有所帮助:

查找apc.ini文件以进行上述c33s建议的更改,并设置建议的数量:http : //www.untwistedvortex.com/optimizing-tuning-apc-alternate-php-cache/

了解什么是apc.ttl:http://www.php.net/manual/zh/apc.configuration.php#ini.apc.ttl

了解什么是apc.shm_size:http ://www.php.net/manual/zh/apc.configuration.php#ini.apc.shm-size


谢谢,您指出了正确的解决方案。降低TTL就像禁用APC。
2012年

4

正如Bokan所提到的,您可以增加内存(如果有),并且他对TTL设置为0的适得其反是正确的。

注意:这就是我针对特定问题解决此错误的方法。它是一个通用的问题,可能是由于事务分配引起的,因此,如果您收到错误并且认为是由重复的PHP文件加载到APC中引起的,则仅遵循以下内容。

我遇到的问题是当我发布PHP应用程序的新版本时。即用新文件替换了我所有的.php文件,APC会将这两个版本都加载到缓存中。

因为我没有足够的内存来存储两个版本的php文件,所以APC将耗尽内存。

有一个名为apc.stat的选项可以告诉APC检查特定文件是否已更改,如果已更改,则通常可以进行开发,因为您不断进行更改,但是在生产环境中通常会像在我的产品中一样将其关闭案例-http: //www.php.net/manual/zh/apc.configuration.php#ini.apc.stat

如果您对性能没有问题,则打开apc.stat将解决此问题。

我想出的解决方案是检查项目版本是否已更改,如果已更改,则清空缓存并重新加载页面。

define('PROJECT_VERSION', '0.28'); 

if(apc_exists('MY_APP_VERSION') ){

    if(apc_fetch('MY_APP_VERSION') != PROJECT_VERSION){
        apc_clear_cache();
        apc_store ('MY_APP_VERSION', PROJECT_VERSION);
        header('Location: ' . 'http'.(empty($_SERVER['HTTPS'])?'':'s').'://'.$_SERVER['SERVER_NAME'].$_SERVER['REQUEST_URI']);
        exit;  
    }

}else{
    apc_store ('MY_APP_VERSION', PROJECT_VERSION);
}

2

这对我们的人有用(在同一台服务器上运行许多Wordpress网站)。

更改了/etc/php.d/apc.ini文件中的内存设置。它设置为64M,因此我们将其加倍为128M。

apc.shm_size = 128M


1

查看互联网可能有多种原因。就我而言,除了...以外的所有内容都保留为默认值

apc.shm_size = 64M

...清除了我早些时候收到的无数警告。


1

将OpenCart安装移动到其他服务器后,收到错误消息“无法为池分配内存”。我也尝试提高memory_limit。

我更改了错误消息中文件的权限以使apache运行的用户(apache,www-data等)具有写访问权限后,错误停止。我没有直接修改/ etc / group(或将文件更改为0777),而是使用了usermod:

usermod -a -G vhost-user-group apache-user

然后,我必须重新启动apache才能使更改生效:

apachectl restart

要么

sudo /etc/init.d/httpd restart

或您的系统用来重启apache的任何东西。

如果该站点位于共享主机上,也许您必须使用FTP程序更改文件权限,或者与主机提供商联系?


1

要解决此问题,请将apc.shm_size的值设置为整数找到您的apc.ini文件(在我的系统中,apc.ini文件位置为/etc/php5/conf.d/apc.ini)并设置: apc.shm_size = 1000


1

在我的系统上,我必须将apc.shm_size = 64M插入/usr/local/etc/php.ini(FreeBSD 9.1)中,然后当我查看apc.php(从/ usr / local / share / doc / APC复制的文件)时/apc.php到/ usr / local / www / apache24 / data),我发现缓存大小已从默认的32M增加到64M,并且我不再有大量的缓存了

参考:http : //au1.php.net/manual/en/apc.configuration.php 还阅读了Bokan的评论,它们非常有帮助


0

监视您的缓存文件大小(您可以使用apc pecl包中的apc.php)并根据需要增加apc.shm_size。

这样就解决了问题。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.