允许的内存大小 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

您的问题似乎是因为表格的列中有longbloblongtext

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字节已用尽

图像迁移脚本 - 允许的 134217728 字节内存大小已用尽 [重复]

致命错误:PHPExcel 中已用尽的允许内存大小为 134217728 字节