PHP内存不足,出现致命错误:允许的内存大小为X字节(已尝试分配Y字节)
我正忙于将一个用PHP/MySQL编写的客户应用程序从Hetzner迁移到AWS。除了一些脚本,一切都很好。这些脚本编写得很糟糕,在数百万条记录中循环,在每次循环中创建数百个局部变量,将每一行写入excel文件,打开另一个文件,编写状态更新,并在每次循环中关闭一个文件。脚本是使用主web应用程序中的PHP内存不足,出现致命错误:允许的内存大小为X字节(已尝试分配Y字节),php,apache,amazon-web-services,amazon-ec2,amazon-aurora,Php,Apache,Amazon Web Services,Amazon Ec2,Amazon Aurora,我正忙于将一个用PHP/MySQL编写的客户应用程序从Hetzner迁移到AWS。除了一些脚本,一切都很好。这些脚本编写得很糟糕,在数百万条记录中循环,在每次循环中创建数百个局部变量,将每一行写入excel文件,打开另一个文件,编写状态更新,并在每次循环中关闭一个文件。脚本是使用主web应用程序中的shell\u exec作为独立进程生成的 当我第一次在EC2上测试脚本时,它很快崩溃了,因为在我的EC2实例上phpmemory\u limit参数被设置为128M。错误与下面的错误类似: Fata
shell\u exec
作为独立进程生成的
当我第一次在EC2上测试脚本时,它很快崩溃了,因为在我的EC2实例上phpmemory\u limit
参数被设置为128M
。错误与下面的错误类似:
Fatal error: Allowed memory size of X bytes exhausted (tried to allocate Y bytes)
我将内存限制从128M
增加到256M
,然后增加到512M
,然后增加到1024M
,4096M
,最后设置为-1
,以查看问题所在
将其设置为-1
一开始似乎确实有效,但随后它冻结了整个实例(t2.micro)。然后我意识到,正是由于缺少交换空间,系统内存限制才得以达到,因此仅出于测试目的,我添加了4GB的交换空间,并将内存限制设置为-1
。这确实像预期的那样工作,脚本从未崩溃,但随着脚本的运行,它逐渐变慢。例如,它将前10%的记录写入excel文件的速度远远快于50%之后的10%。所有这些,我看着内存使用扩展到6GB
以下是脚本运行时的htop
屏幕截图:
除了设置为-1的memory\u limit
之外,我使用的是php安装附带的默认php.ini
但是,当我在另一台服务器(本例中为Hetzner共享主机)上运行相同的脚本时,服务器会以某种方式限制内存使用,并且脚本在memory\u limit
设置的128M
上运行良好。虽然这并不完全正确(服务器上的htop
证实了这一点),但它似乎不会在内存/交换空间比我的EC2实例少得多的服务器上崩溃
以下是在Hetzner上运行的htop
截图:
第三个屏幕截图是在脚本末尾拍摄的,正如你所看到的,从脚本开始到结束,内存没有太大变化。以下是服务器的php.ini
设置:
display_errors=1
memory_limit=128M
max_execution_time=90
max_input_vars=3500
upload_max_filesize=64M
post_max_size=64M
allow_url_fopen=0
在这两种情况下,数据库和代码库都是精确的副本。在这两种情况下,生成的excel文件大小约为225MB
那么,有什么想法可能会导致这种行为,我应该如何着手在我的EC2实例上修复它
谢谢你的帮助
EasyPHP-Devserver-17-depanne-erreur致命错误:允许的内存大小
中已耗尽的134217728字节(尝试分配471698889字节)
C:\程序文件
(x86)\EasyPHP-Devserver-17\eds二进制文件\httpserver\apache2425vc11x86x180705170153\eds-app-dashboard.php
在线77
解决方案
在我的例子中,这是因为EasyHP试图加载过大的error.log文件
删除eds binaries\httpserver\apache2418x160331124251\logs中的服务器日志文件
测试正常
EasyPHP-Devserver-17-depanne-erreur致命错误:允许的内存大小
中已耗尽的134217728字节(尝试分配471698889字节)
C:\程序文件
(x86)\EasyPHP-Devserver-17\eds二进制文件\httpserver\apache2425vc11x86x180705170153\eds-app-dashboard.php
在线77
解决方案
在我的例子中,这是因为EasyHP试图加载过大的error.log文件
删除eds binaries\httpserver\apache2418x160331124251\logs中的服务器日志文件
测试正常您可以做的最好的事情是提高脚本的效率。Hetzner实例也使用了大约5G的内存,因此该服务器上的php.ini也必须被某些内容覆盖。不确定我是否遗漏了一些内容,但Hetzner实例并没有仅对脚本使用5GB。正如我所说,它是一个共享实例,您看到的4686/15964MB
是服务器上运行的所有帐户/进程(不仅仅是我的帐户/进程)的内存使用情况。如果你看EC2和Hetzner屏幕截图中PHP脚本的VIRT和RES列,在内存消耗方面似乎存在巨大差异。是的,很抱歉我误读了,Hetzner服务器是虚拟的还是物理的?不用担心。它是一个“共享”托管包,但看起来像是多个用户/客户之间共享的物理服务器(不是虚拟机)。我给他们发了一封电子邮件来澄清。我提出的两个建议是:比较两台服务器之间的php版本和已安装的扩展,并优化php脚本,以便在使用完变量后释放内存。最好的办法是提高脚本的效率。Hetzner实例也使用了大约5G的内存,因此该服务器上的php.ini也必须被某些内容覆盖。不确定我是否遗漏了一些内容,但Hetzner实例并没有仅对脚本使用5GB。正如我所说,它是一个共享实例,您看到的4686/15964MB
是服务器上运行的所有帐户/进程(不仅仅是我的帐户/进程)的内存使用情况。如果你看EC2和Hetzner屏幕截图中PHP脚本的VIRT和RES列,在内存消耗方面似乎存在巨大差异。是的,很抱歉我误读了,Hetzner服务器是虚拟的还是物理的?不用担心。它是一个“共享”托管包,但看起来像是多个用户/客户之间共享的物理服务器(不是虚拟机)。我给他们发了一封电子邮件来澄清。我的两个建议是:比较两台服务器之间的php版本和已安装的扩展