【问题标题】:Memory leak in PHP when fetching large dataset from MySQL从 MySQL 获取大型数据集时 PHP 中的内存泄漏
【发布时间】:2012-01-14 14:26:20
【问题描述】:

当我为大约 60,000 条记录的用户表执行以下代码时:

mysql_connect("localhost", "root", "");
mysql_select_db("test");

$result = mysql_query("select * from users");

while ($row = mysql_fetch_object($result)) {
  echo(convert(memory_get_usage(true))."\n");
}


function convert($size) {
  $unit=array('b','kb','mb','gb','tb','pb');
  return @round($size/pow(1024,($i=floor(log($size,1024)))),2).' '.$unit[$i];
}

我收到以下错误:

PHP Fatal error:  Allowed memory size of 134217728 bytes exhausted (tried to allocate 32 bytes)

关于如何避免脚本在每次循环中占用额外内存的任何想法?在我的实际代码中,我尝试为大型数据集提供 CSV 下载,并进行一些 PHP 预处理。

请不要建议增加 PHP 的内存限制——这是一个坏主意,更重要的是,仍然会限制使用这种技术可以处理的数据集的大小。

【问题讨论】:

  • 为什么不尝试分页查询???
  • 这篇文章的标题具有误导性。这不是内存泄漏,您正在以超出预设内存限制的方式处理巨大的结果。
  • @Galled -- 我正在将这些数据转储到 CSV,所以分页并不是一个真正的选择。

标签: php mysql memory-leaks


【解决方案1】:

mysql_query 将整个结果集缓冲到 php 内存中。这很方便,而且通常非常快,但是您遇到了一个缺点。

mysql_unbuffered_query() 存在。它不会一次抓取整个结果集。当您从结果集中获取行时,它会一次抓取小块。

【讨论】:

  • 谢谢克里斯,这正是我想要的。 MySQL 的默认行为是为每一行获取额外的内存,这似乎很奇怪(即使是按顺序获取而不是显式地将数据存储在内存中),但是你有它。
【解决方案2】:

我不能 100% 确定这是否能解决您的问题,但您是否考虑过使用 PDO?它有几个优点;你可以阅读更多关于他们的信息here。如果您确实朝那个方向发展,那么还有一个关于内存使用的类似问题here

【讨论】:

    【解决方案3】:

    我也遇到过类似的问题。我所做的是创建一个临时文件(您可以使用哈希或类似的东西来记录名称)。

    • 提取 10,000 行并将它们放入一个文件 (temp)。将其放入临时 csv 文件中。
    • 重新加载页面(使用带有特定参数/会话的标题)
    • 再提取 10,000 行并将其附加到文件中。
    • 当您到达表格末尾时 - 向用户缓冲文件。

    像这样绕着圈子,直到你搞定为止。我不得不做这个工作有两个原因,

    1. 超时
    2. 内存不足错误。
    此方法的

    缺点是它需要多次 HTTP 调用才能获取数据。同时也可能有行已经改变等。这是一种非常“肮脏”的方式。我还没有找到更好的东西。希望对您有所帮助。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2015-05-06
      • 2023-03-17
      • 2011-11-05
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多