允许的内存大小 134217728 字节用尽(尝试分配 4294967296 字节)
Posted
技术标签:
【中文标题】允许的内存大小 134217728 字节用尽(尝试分配 4294967296 字节)【英文标题】:Allowed memory size of 134217728 bytes exhausted (tried to allocate 4294967296 bytes) 【发布时间】:2013-08-09 21:44:25 【问题描述】:我的项目使用了一个开源的 php mysql 库https://github.com/ajillion/PHP-MySQLi-Database-Class
但是项目年中报告:“致命错误:在/home1/flipalbu/public_html/kvisofttest/login-admin/Lib/class.MysqliDb.php中允许的内存大小为134217728字节用尽(试图分配4294967296字节)在第 422 行”这个错误,
我的服务器是:linux x86_64
PHP 版本 5.4.17
Mysql 版本:5.5.32
memory_limit = 128M
第 422 行:call_user_func_array (array ($ stmt, 'bind_result'), $ parameters);
查询部分代码:
$ db = new MysqliDb ('LocalHost', 'root', 'PASSWD', 'DB');
$ wqdb = $ db-> query ("SELECT * FROM db_table");
foreach ($ wqdb as $ row)
$ con. = $ row ['ID'];
echo $ con;
有什么办法可以解决吗?
/** 错误代码**/
protected function _dynamicBindResults(mysqli_stmt $stmt)
$parameters = array();
$results = array();
$meta = $stmt->result_metadata();
$row = array();
while ($field = $meta->fetch_field())
$row[$field->name] = null;
$parameters[] = & $row[$field->name];
call_user_func_array(array($stmt, 'bind_result'), $parameters);
while ($stmt->fetch())
$x = array();
foreach ($row as $key => $val)
$x[$key] = $val;
array_push($results, $x);
return $results;
【问题讨论】:
您正在耗尽 PHP 可用的内存。大概是因为您的数据库表很大,并且您只是选择了没有条件或限制子句的所有记录。 你要获取多少行? 有 - 不要从数据库中选择所有内容。 将内存限制增加到最大值ini_set('memory_limit', '-1');
@User016,不;这可能是命令行上的解决方案(即使那样,也很少)。但是,这看起来是一个 Web 应用程序,您不希望实例占用大量内存。查询需要优化。
【参考方案1】:
我在这里阅读了这个错误报告:https://bugs.php.net/bug.php?id=51386
您的问题似乎是因为表格的列中有longblob
或longtext
。
longtext
/ longblob
的最大长度为 4294967295
[4GB] 这就是为什么 mysqli 会尝试为缓冲区分配内存以确保没有丢失任何内容。我建议您使用mediumtext
(16777215 [16MB] 最大长度),这通常足以满足所有需求。
更新: 因为这个答案已经看到了一些活动,所以我从 Phil_1984 添加了这个解决方案(参见 cmets)
我使用 mysqli,在阅读了 php dev 的引用后,添加了一个 $stmt->store_result();在 execute 和 bind_result 之间似乎修复了 我的问题
=> 如果您使用$stmt->store_result()
,您可以将mysqli 与longblob
/ longtext
一起使用而不会出现错误。
-
旧答案: 我建议您将列更改为另一种类型(mediumtext)或使用 PDO(我认为它没有那个问题)。但是如果你想将列保持为长文本,你必须切换你的mysql库
引用自 PHP 开发人员:
这是使用 libmysql 时 ext/mysqli 的一个已知限制(总是 在 5.2 和更早版本中)以及使用 5.3 启用 libmysql 时。这 原因是服务器发送的关于 柱子。这个长文本的最大长度为 4G,而 ext/mysqli 试图 绑定最大长度,以确保不会发生数据丢失(数据不会 适合 C 级别的绑定缓冲区)。但是,这意味着 4G longtext/longblob 列。 ext/mysqli 已更改为有一种方法 解决这个问题。您需要调用 mysqli_stmt_store_result() 哪个 将数据存储在本地,这当然意味着更高的内存 PHP 的用法。但是,因为您使用 libmysql 这不会命中 当然,PHP 的内存限制。在 store_result 期间,max_length 的 将计算每一列,然后在执行 bind_result 时 只会分配一个大小为 max_length 的缓冲区,这将是 肯定低于4G。总之,准备执行store_result bind_result fetch...fetch...fetch
【讨论】:
嗯,我用你的方法测试了一下。 我使用 mysqli,在阅读了 php dev 的引用后,在 execute 和 bind_result 之间添加$stmt->store_result();
似乎可以解决我的问题。
@Phil_1984_ 你让我免于用那条小线在我的显示器上打一个整体,非常感谢【参考方案2】:
您超出了最大可用内存。你有两个选择:
通过配置(php.ini
中的memory_limit
指令)或使用ini_set('memory_limit', '200M')
在执行时间增加每个 PHP 脚本的最大允许内存
改进代码以仅处理所需信息。
【讨论】:
谢谢,看来需要修改查询了。【参考方案3】:看起来不像是一张大桌子!似乎是一个无限循环!它试图分配大约 4gb,我不认为你有这么大的表....
检查您没有在此处创建循环:
call_user_func_array (array ($ stmt, 'bind_result'), $ parameters);
也许您应该发布这一行附近的代码。
【讨论】:
是的,但是一个程序员刚入门,不知道从那时起检测到【参考方案4】:如果您尝试一次读取整个表,并且该表有很多行和列,那么内存不足是不可避免的。您可以通过提高 php.ini 中的内存限制来推迟它,但问题只会在您添加几千行时再次出现。
您需要重写您的脚本,以便更清楚地了解它获取的内容。如果您只需要特定的记录,那么拉下整个表并在结果集中查找您想要的行是非常低效的。使用 WHERE 子句指定您真正想要获得的内容。 PHP/SQL 应用程序的经验法则是“尽可能使用 SQL 来指定你想要的,然后在 PHP 中做你需要做的事情”。
当然,您需要在 PHP 中处理整个表可能是完全正当的理由。在这种情况下,您应该使用 LIMIT 和 OFFSET 以块的形式(例如一次 100 行)获取数据,处理这些行,获取下一个块,处理这些等等,直到您遍历整个表。这比尝试一次加载整个表的内存要少得多
【讨论】:
Works 在本地虚拟机可以完全运行本地虚拟机的内存是128MB,使用命令'top'控制,不会因为查询占用太多内存。但是,一进服务器就会产生这个问题,我需要重新更改整个项目的所有查询吗?还给出了这个代码示例: SELECT * FROM db_table ORDER BY page_modified DESC, ID DESC LIMIT $ startItem, $ itemsPerPage $ startItem = 0 $ itemsPerPage = 10 live 上的表可能比你的 test 表大得多。您的脚本正在尝试分配 4 GB 你真的应该看看我的回答,这是一个已知问题,甚至不是bug,它的mysqli + longtext 或longblob 我的表只有几百条数据。 @x4rf41 答案是什么?我不使用这个网站,对不起。以上是关于允许的内存大小 134217728 字节用尽(尝试分配 4294967296 字节)的主要内容,如果未能解决你的问题,请参考以下文章
允许的内存大小 134217728 字节用尽(尝试分配 1052672 字节)
允许的内存大小为 134217728 字节已用尽(尝试分配 42 字节)[关闭]
php - 致命错误:允许的内存大小为 134217728 字节已用尽 [重复]
PHP致命错误:允许的内存大小为134217728字节已用尽