【问题标题】:PHP - Memory leak when fetching large tables from mysqlPHP - 从 mysql 获取大表时内存泄漏
【发布时间】:2017-07-24 22:53:59
【问题描述】:

(使用 pdo)

所以我有一个要从中获取的几乎 1 GB 大小的表。同时,我正在处理我获取的数据,然后将其插入到多个其他表中。我的代码如下所示:

$stmt = $pdo->query("SELECT * FROM foo");

$stmt2 = $pdo->prepare("INSERT INTO bar (col1) VALUES (?)");
$stmt3 = //...etc

while($row = $stmt->fetch(PDO::FETCH_ASSOC)) {
    $toInsert = doStuff($row['baz']);
    $stmt2->execute(array($toInsert));

    //etc.
}

每当我在整个表上运行脚本时,它都会耗尽内存。我可以给它更多,但我觉得有更好的方法。

我认为无缓冲查询可能会解决问题,但我需要同时运行这些查询。

【问题讨论】:

  • INSERT INTO bar (col1) (SELECT baz FROM foo)
  • 做批处理,一次100条记录,做一个日志表,以防任何特定行出现问题。

标签: php mysql pdo


【解决方案1】:

是否可以使用无缓冲查询来读取并为您的插入操作设置另一个 PDO 连接是一种解决方案?

【讨论】:

  • 谢谢,这成功了!我之前在同一个 PDO 对象上用这个 sn-p 代码尝试过这个想法:$statement = $pdo->prepare("SELECT * FROM $RawPDBData",array(PDO::MYSQL_ATTR_USE_BUFFERED_QUERY => false)); $statement->execute(); 但这不起作用。知道为什么一个新的 PDO 对象可以工作,但不是这个吗?
  • 一个无缓冲的查询阻塞了当前的 (PDO) 连接,直到从 (MySQL) 服务器获取完整的结果集。这就是为什么您不能同时重复使用同一个连接并且您必须为其他查询使用第二个连接。
  • 澄清一下,当我说它不起作用时,我的意思是代码运行但仍然存在内存泄漏。它表现得好像我传递给 prepare() 的额外属性甚至不存在。为什么这至少没有为后续并发查询抛出错误?
  • 奇怪...从你写的内容来看,你应该收到一个错误。
【解决方案2】:

当您从数据库中读取数据并在 PHP 中使用它时,PHP 对象也会占用内存以及 MySQL(用于工作并返回结果)。

您的查询看起来很简单。您可以编写一个包含两个查询的语句。这样它就可以在没有 PHP 内存问题的情况下工作。

【讨论】:

    【解决方案3】:

    尝试使用limit和offset进行分页

    $limit = 1000;
    $offset = 0;
    
    $stmt = $pdo->prepare("SELECT * FROM foo ORDER BY id ACC LIMIT :limit OFFSET :offset");
    
    $hadResult = false;
    do {
        $stmt->bindParam(':limit', $pageSize, PDO::PARAM_INT);
        $stmt->bindParam(':offset', $offset, PDO::PARAM_INT);
    
        while($row = $stmt->fetch(PDO::FETCH_ASSOC)) {
            $hadResult = true;
            ///do stuff
        }
        $offset += $limit;
    } while($hadResult);
    

    【讨论】:

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