PHP 在 PHP.ini 文件中全局设置了内存限制。我还知道它们可以在本地级别进行配置。
我们的查询内存限制设置为 132MB,但我们不断收到如下错误:
Fatal error: Allowed memory size of 161480704 bytes exhausted (tried to allocate 32 bytes) in #{removed_file_path}/script.php on line #{line}
目前,我们正在通过错误日志文件监控我们的系统,该文件会在用户浏览页面以及使用时缓存错误cron
;然而,这些不会被记录在任何地方。
mysql_query
可以通过更改对to 的任何调用来修复该错误mysql_unbuffered_query
,但是我需要知道服务器上的所有文件需要在哪里进行更改。如果脚本实际上没有内存问题,那么我不想更改代码,因为我希望服务器尽可能将结果读取到 RAM。
我们不想增加 PHP 的内存限制,因为我们的主机建议我们不要这样做。
可以采取什么措施来解决内存问题?我们正在 CentOS 6.7 上运行。
答案1
您的 PHP 解释器设置为终止任何需要超过 132MB 内存的脚本。您的脚本正在尝试分配超过 161MB 的内存。问题很简单,解决方案也很简单。您可以:
- 让你的 PHP 解释器分配更多。您的主机建议不要这样做的原因是,如果他不这样做,他最终会为您分配 8GB 以上的内存,因为您的数据库不断增长。
- 忘记 PHP 和已弃用的
mysql_*
API,并使用不强制执行此类内存限制的东西。请记住,即使解释器不再打扰您,操作系统也可能会在某个时候打扰您。 - 改进你的脚本。
使用mysql_unbuffered_query
与解决方案 #3 相匹配的方法。由于 PHP 不再缓冲 MySQL 结果集,因此它不再占用太多内存,并且解释器也不再抱怨。你基本上是在切换从缓冲查询到无缓冲查询(参见示例#2 和#3,并考虑切换到 PDO,这是 2016 年)。如果您想继续使用 PHP,并且您认为您的设计是正确的,那么这就是您的解决方案。
我不想更改代码,因为我希望服务器尽可能将结果读取到 RAM。
从事 DBMS 工作的人通常都做得很好。他们的引擎经过优化,查询不会花费比其需要更多的时间。考虑到您使用的是 PHP 和旧的mysql_*
API,您不会让我相信速度真的是一个令人担忧的问题...... 我的猜测是:您可以将数据保存在数据库中,而不是 RAM 中。使用无缓冲查询,一次获取/处理一行,并更多地依赖您的 DBMS(此外,它可能会为您做一些缓冲...)。
如果您仍然不相信,可能的改进可能是重新考虑查询本身。您确定您获取的数据没有超出您的需要吗?SELECT *
(我的意思是,您在查询开始时真的需要它吗?)您确定 MySQL 无法为您处理某些处理吗? DBMS 是非常强大的工具,让它们发挥作用,而不是在 PHP 脚本中完成所有操作。一个典型的例子是计算平均值:不是获取列中的所有数字并使用求和循环,而是AVG(column)
直接询问。
如果没有您的脚本,我很难就这部分提供进一步的建议(Stack Overflow 的人员可能会做得更好)。但是,如果此时您认为您已经对脚本进行了足够的修改...那么将其提交给代码审查?如果你找不到进一步改进的方法,那么那里的人很可能会找到。
如果在某个时候,您觉得您已经用尽了 PHP 和 MySQL 提供的所有选项,我认为您将不得不考虑使用其他东西。根据您正在进行的数据处理类型,您也许能够找到更适合手头任务的其他工具。