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


Allowed memory size of 134217728 bytes exhausted (tried to allocate 4294967296 bytes)

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

但该项目的年中报告:"致命错误:允许的内存大小134217728字节耗尽(试图分配4294967296字节)在/home1/flipalbu/public_html/kvsisottest/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;
        }

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

您的问题似乎是因为表的列中存在longbloblongtext

longtext/longblob的最大长度为4294967295[4GB],这就是为什么mysqli试图为缓冲区分配内存以确保不会丢失任何东西。我建议您使用mediumtext(16777215[16MB]最大长度),这通常应该足以满足所有要求。

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

我使用mysqli,在阅读了php-dev的那句话后,添加了$stmt->store_result();execute和bind_result之间似乎修复了的问题

=>如果使用$stmt->store_result(),则可以将mysqli与longblob/longtext一起使用而不会出现错误。

-

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

PHP开发人员报价:

这是ext/mysqli在使用libmysql时的一个已知限制(总是在5.2和以前的版本中),并且当libmysql与5.3一起启用时原因是服务器发送的关于柱这个长文本的最大长度为4G,ext/mysqli尝试使用最大长度绑定,以确保不会发生数据丢失(数据不会适合于C级的绑定缓冲区)。然而,这意味着4Glongtext/longblob列。ext/mysqli已被更改为解决这个问题。您需要调用mysqli_stmt_store_result()将在本地存储数据,这当然意味着更高的内存PHP的用法。然而,因为您使用libmysql,所以这不会影响PHP的内存限制是肯定的。在store_result期间将计算每一列,然后在执行bind_result时将只分配一个大小为max_length的缓冲区,该缓冲区将肯定低于4G。简而言之,prepare execute store_resultbind_result获取。。。取来提取

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

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

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

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

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

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

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

您已超过可用内存的最大值。你有两个选择:

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

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

相关文章: