是啥导致 PHP 中的“无法为池分配内存”?
Posted
技术标签:
【中文标题】是啥导致 PHP 中的“无法为池分配内存”?【英文标题】:What is causing "Unable to allocate memory for pool" in PHP?是什么导致 PHP 中的“无法为池分配内存”? 【发布时间】:2011-04-13 00:08:39 【问题描述】:我偶尔会遇到服务器的内存分配限制,特别是对于像 Wordpress 这样臃肿的应用程序,但从未遇到“无法为池分配内存”并且无法追踪任何信息。
有人知道这是什么意思吗?我试过增加memory_limit
没有成功。我也没有对应用程序进行任何重大更改。一天没问题,第二天就报这个错误。
【问题讨论】:
【参考方案1】:Probably is APC related.
对于遇到此问题的人,请指定您的 .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
【讨论】:
谢谢!这正是我一直在寻找的链接。感谢您的帮助! 我发现这些更改并不能解决问题,因为链接线程上的 cmets 也记录了... 有关此 APC 设置的更多信息:php.net/apc.configuration#ini.apc.mmap-file-mask 就我而言,我必须从文件支持更改为符合 POSIX 标准才能消除错误。 我不知道这个答案如何解决问题。当file_mask
不是这些值之一时,是否会发生错误?如果我有这些值之一并且我收到错误,是否需要将其切换为其他值?哪一个?【参考方案2】:
我的解决方案:
apc.ttl=0 apc.shm_size=你想要的任何东西编辑开始
警告!
@bokan 告诉我我应该在此处添加警告。
如果您的 ttl 为 0,这意味着可以立即清除每个缓存的项目。因此,如果您的缓存大小较小,例如 2mb 且 ttl 为 0,这将使 apc 无用,因为缓存中的数据总是会被覆盖。
降低ttl仅意味着缓存不会变满,只有无法替换的项目。
所以你必须在 ttl 和缓存大小之间选择一个好的平衡点。
在我的情况下,我的缓存大小为 1gb,所以对我来说已经足够了。
编辑结束
在使用 php 5.2.17 的 centos 5 上遇到了同样的问题,并注意到如果 缓存大小很小,ttl 参数为“高”(如 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,你有一个很好的图表你的缓存使用情况
【讨论】:
谢谢,这确实有帮助。我每秒收到大约十几个“无法分配内存”错误。我将缓存大小加倍(32 到 64 MB)并将 ttl 降为 0。这完全消除了这些错误。 这是我们服务器上的修复。 这似乎也解决了我的问题。 使用 ZWAMP,这似乎也成功了。谢谢。 这不是解决方案!错误消失,但 APC 将几乎被禁用。每次内存已满时,它将刷新所有缓存。只需阅读 Brideau 给我们的手册即可。 php.net/manual/en/apc.configuration.php#ini.apc.ttl.【参考方案3】:运行 apc.php 脚本是了解您的问题所在的关键,IMO。这有助于我们正确调整缓存大小,目前似乎已经解决了问题。
【讨论】:
如 c33s 所说:下载 pecl.php.net/get/APC 提取并运行 apc.php,你有一个很好的图表,你的缓存使用情况如何【参考方案4】:对于像我这样的新手,这些资源有帮助:
找到 apc.ini 文件以进行上述 c33s 推荐的更改,并设置推荐量: http://www.untwistedvortex.com/optimizing-tuning-apc-alternate-php-cache/
了解 apc.ttl 是什么: http://www.php.net/manual/en/apc.configuration.php#ini.apc.ttl
了解 apc.shm_size 是什么: http://www.php.net/manual/en/apc.configuration.php#ini.apc.shm-size
【讨论】:
谢谢,您指出了正确的解决方案。降低 TTL 就像禁用 APC。【参考方案5】:查看互联网可能有多种原因。 在我的情况下,除了...
apc.shm_size = 64M
...清除了我之前收到的无数警告。
【讨论】:
【参考方案6】:使用 0 的 TTL 意味着 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 文件被缓存。
但切勿使用 0 的 TTL。
正如 c33s 所说,使用 apc.php 检查您的配置。将文件从 apc 包复制到 web 文件夹并将浏览器指向它。您将看到真正分配了什么以及如何使用它。图表必须在几个小时后保持稳定,如果它们在每次刷新时都完全改变,那么这意味着你的设置是错误的(APC 正在刷新所有内容)。分配比 APC 实际用作安全边际的内存多 20% 的内存,并定期检查。
仅允许 32MB 的默认值低得离谱。 PHP 是在服务器为 64MB 时设计的,大多数脚本每页使用一个 php 文件。如今,像 Magento 这样的解决方案需要超过 10k 的文件(在 APC 中约为 60Mb)。您应该允许足够的内存,以便始终缓存大多数 php 文件。这不是浪费,将操作码保存在 ram 中比在文件缓存中保存相应的原始 php 更有效。 如今,我们可以以低至每月 80 美元的价格找到具有 24Gb 内存的专用服务器,因此请不要犹豫,为 APC 留出几 GB 的内存。我在托管 5Magento 商店和约 40 个 wordpress 网站的服务器上放了 24GB 中的 2GB,APC 使用 1.2GB。 Magento 安装需要 64MB,带有一些插件的 Wordpress 需要 40MB。
另外,如果您在同一台服务器上有开发网站。从缓存中排除它们。
【讨论】:
这个!我正在运行 Wordpress,而 32M 还不够。高达 64M,现在很清楚。检查 apc.php 人! 要增加到 64M,您需要添加 apc.shm_size=64 而不是 apc.shm_size=64M (我见过的大多数示例最后都有一个 M)不适用于我的版本apc (v3.1.3p1) 您假设您将有大量缓存文件在缓存中的时间超过 TTL。 c33s有一个重点。如果所有内容都是最近访问过的(假设您有 70% 的缓存可以按照您的意愿随时访问,并且有一个很大的峰值,其中一次添加了许多额外的不常用文件),您将收到错误抛出 TTL 秒。缓存已满,您告诉 APC 它不应该清除这些条目,因此它会抱怨。如果您有 5 小时的 TTL,那么最终会出现 5 小时的错误等待那些不常见的文件过期。 @MatthewKolb :您不应该允许缓存超过 APC 在其内存中可以容纳的文件。使用过滤器防止不经常访问的文件被缓存。 @Patrick Forget:这取决于... 【参考方案7】:正如 Bokan 所提到的,如果内存可用,您可以增加内存,他说的正确,将 TTL 设置为 0 会适得其反。
注意:这就是我针对特定问题修复此错误的方法。这是一个一般性问题,可能是由很多事情引起的,所以如果您收到错误并且您认为它是由重复的 PHP 文件加载到 APC 中引起的,请按照以下说明操作。
我遇到的问题是当我发布我的 PHP 应用程序的新版本时。即用新文件替换我所有的 .php 文件 APC 会将两个版本都加载到缓存中。
因为我没有足够的内存来存放两个版本的 php 文件 APC 会耗尽内存。
有一个名为 apc.stat 的选项告诉 APC 检查特定文件是否已更改,如果更改则替换它,这对于开发来说通常是可以的,因为你不断地进行更改,但在生产时它通常会像以前一样关闭在我的情况下 - http://www.php.net/manual/en/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);
【讨论】:
【参考方案8】:将 OpenCart 安装移动到其他服务器后,我收到错误“无法为池分配内存”。我也尝试提高 memory_limit。
在我将错误消息中的文件权限更改为具有运行 apache 的用户(apache、www-data 等)的写访问权限后,错误停止了。我没有直接修改 /etc/group(或 chmod-ing 文件为 0777),而是使用了 usermod:
usermod -a -G vhost-user-group apache-user
然后我必须重新启动 apache 才能使更改生效:
apachectl restart
或者
sudo /etc/init.d/httpd restart
或者你的系统使用什么来重启 apache。
如果站点在共享主机上,也许您必须使用 FTP 程序更改文件权限,或联系主机提供商?
【讨论】:
【参考方案9】:监控您的缓存文件大小(您可以使用 apc pecl 包中的 apc.php)并增加 apc.shm_size 根据您的需要。
这样就解决了问题。
【讨论】:
【参考方案10】:要解决此问题,请将 apc.shm_size 的值设置为整数 找到您的 apc.ini 文件(在我的系统 apc.ini 文件位置 /etc/php5/conf.d/apc.ini 中)并设置: apc.shm_size = 1000
【讨论】:
【参考方案11】:这对我们的人有用(在同一台服务器上运行大量 Wordpress 网站)。
更改了 /etc/php.d/apc.ini 文件中的内存设置。它被设置为 64M,所以我们将其翻倍为 128M。
apc.shm_size=128M
【讨论】:
【参考方案12】:在我的系统上我必须插入 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 还看了博坎的cmets,很有帮助
【讨论】:
以上是关于是啥导致 PHP 中的“无法为池分配内存”?的主要内容,如果未能解决你的问题,请参考以下文章
当为“var”和“let”分配一个引发错误的函数的返回值时,是啥导致了它们之间的不同行为