允许的内存大小为134217728字节耗尽(尝试分配4294967296字节)

时间:2013-08-08 08:44:54

标签: php mysql

我的项目使用开源PHP MySQL库https://github.com/ajillion/PHP-MySQLi-Database-Class

但项目年中报告:“致命错误:允许的内存大小为134217728字节耗尽(试图分配4294967296字节)/ home1 / flipalbu / public_html / kvisofttest / login-admin / lib / class.MysqliDb.php在第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;
        }

4 个答案:

答案 0 :(得分:22)

我在这里阅读了这个错误报告:https://bugs.php.net/bug.php?id=51386

您的问题似乎发生了,因为表格的列中有longbloblongtext

longtext / longblob的最大长度为4294967295 [4GB],这就是mysqli尝试为缓冲区分配内存以确保没有丢失的原因。我建议你使用mediumtext(16777215 [16MB]最大长度),这通常应该足够了。

<强>更新 因为这个答案已经看到了一些活动,我从Phil_1984添加了这个解决方案(见评论)

  

我使用mysqli并在阅读php dev中的引用后添加了一个   $ stmt-&GT; store_result();在execute和bind_result之间似乎修复了   给我的问题

=&GT;如果您使用$stmt->store_result(),则可以在longblob / longtext使用mysqli而不会收到错误。

-

旧答案: 我建议您将列更改为另一种类型(mediumtext)或使用PDO(我认为它没有这个问题)。但是如果你想把列保留为longtext,你必须切换你的mysql库

引用PHP Dev:

  

这是使用libmysql时的ext / mysqli的已知限制(总是如此)   在5.2和之前的版本中以及当libmysql启用5.3时。该   原因是服务器没有发送太具体的元数据   柱。此longtext的最大长度为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

答案 1 :(得分:4)

如果您试图一次性读取整个表,并且该表有很多行和列,则内存不足是不可避免的。你可以通过增加php.ini中的内存限制来解决它,但问题只会在你添加几千行时重新出现。

您需要重写脚本以更加明智地了解它所取得的内容。如果您只需要特定记录,那么下拉整个表并在结果集中查找所需的行是非常低效的。使用WHERE子句指定您真正想要获得的内容。 PHP / SQL应用程序的经验法则是“尽可能使用SQL来指定您想要的内容,然后在PHP中执行您需要执行的操作”。

当然,可能有一个完全正当的理由需要在PHP中处理整个表。在这种情况下,您应该使用LIMIT和OFFSET以块(一次说100行)获取数据,处理这些行,获取下一个块,处理这些行等等,直到您完成整个表。这比尝试一次加载整个表的内存要少得多

答案 2 :(得分:1)

看起来不像是一张巨大的桌子!好像无尽的循环!它试图分配大约4gb,我不认为你有这么大的桌子......

检查您是否在此处创建循环:

call_user_func_array (array ($ stmt, 'bind_result'), $ parameters);

也许你应该发布这一行的代码。

答案 3 :(得分:0)

你超过了最大可用内存。你有两个选择:

  • 通过配置(memory_limit中的php.ini指令)或使用ini_set('memory_limit', '200M')

  • 的执行时间,增加每个PHP脚本的最大允许内存量>
  • 改进代码以仅处理所需信息。