7

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

但项目年中报告:“致命错误:在/home1/flipalbu/public_html/kvisofttest/login-admin/Lib/class.MysqliDb.php第422行中允许的内存大小为134217728字节耗尽(试图分配4294967296字节) “这个错误,

我的服务器是: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

4 回答 4

24

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

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

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

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

我使用 mysqli 并在阅读了 php dev 的引用后,添加了 $stmt->store_result(); 在 execute 和 bind_result 之间似乎解决了我的问题

=> 如果您使用,您可以使用带有/的$stmt->store_result()mysqli而不会出现错误。longbloblongtext

-

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

引用 PHP 开发人员:

这是 ext/mysqli 在使用 libmysql(总是在 5.2 和更早版本中)以及使用 5.3 启用 libmysql 时的已知限制。原因是服务器发送的关于该列的元数据不太具体。此长文本的最大长度为 4G,并且 ext/mysqli 尝试使用最大长度进行绑定,以确保不会发生数据丢失(数据不适合 C 级别的绑定缓冲区)。但是,对于 longtext/longblob 列,这意味着 4G。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

于 2013-08-08T08:58:29.167 回答
4

如果您试图一次读取整个表,并且该表有很多行和列,那么内存不足是不可避免的。您可以通过提高 php.ini 中的内存限制来推迟它,但只有在添加几千行时才会再次出现问题。

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

当然,您需要在 PHP 中处理整个表可能是完全合理的原因。在这种情况下,您应该使用 LIMIT 和 OFFSET 以块的形式(例如一次 100 行)获取数据,处理这些行,获取下一个块,处理这些等等,直到您遍历整个表。这比尝试一次加载整个表的内存要少得多

于 2013-08-08T08:52:43.930 回答
1

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

检查您没有在此处创建循环:

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

也许你应该发布这条线附近的代码。

于 2013-08-08T08:56:23.053 回答
0

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

  • 通过配置(memory_limit指令 in php.ini)或执行时间增加每个 PHP 脚本的最大允许内存使用ini_set('memory_limit', '200M')

  • 改进代码以仅处理所需的信息。

于 2013-08-08T08:58:19.467 回答