Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/mysql/72.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
PHP PDO fetch()循环在处理部分大数据集后死亡_Php_Mysql_Loops_Memory_Pdo - Fatal编程技术网

PHP PDO fetch()循环在处理部分大数据集后死亡

PHP PDO fetch()循环在处理部分大数据集后死亡,php,mysql,loops,memory,pdo,Php,Mysql,Loops,Memory,Pdo,我有一个PHP脚本,它将PDO查询中的一个“大”数据集(大约100K条记录)处理为一个对象集合,在一个典型的循环中: while ($record = $query->fetch()) { $obj = new Thing($record); /* do some processing */ $list[] = $obj; $count++; } error_log('Processed '.$count.' records'); 这个循环处理大约5

我有一个PHP脚本,它将PDO查询中的一个“大”数据集(大约100K条记录)处理为一个对象集合,在一个典型的循环中:

while ($record = $query->fetch()) {
    $obj = new Thing($record);

    /* do some processing */

    $list[] = $obj;
    $count++;
}

error_log('Processed '.$count.' records');
这个循环处理大约50%的数据集,然后莫名其妙地中断

我尝试过的事情:

  • 内存分析:
    Memory\u get\u peak\u usage()
    在循环结束之前始终输出大约63MB的内存。内存限制为512MB,通过php.ini设置
  • 使用
    设置时间限制()
    将脚本执行时间增加到1小时(3600秒)。循环在此之前很久就中断了,我在日志中看不到这个循环的常见错误
  • PDO::MYSQL\u ATTR\u使用\u BUFFERED\u QUERY
    设置为
    false
    ,以避免缓冲整个数据集
  • 循环中断后立即注销
    $query->errorInfo()
    。这没有帮助,因为错误代码是“00000”
  • 正在检查MySQL错误日志。在脚本运行之前、之后或期间,没有任何值得注意的内容
  • 将处理批处理为20K个记录块。没有区别。环路在同一个位置断开。然而,通过在每个批处理结束时“清理”PDO语句对象,我能够使处理的总数达到54%
其他奇怪的行为:

  • 当我使用
    ini\u set('memory\u limit','1024MB')
    设置内存限制时,循环实际上比使用较小内存限制的循环更早结束,大约有20%的进度
  • 在这个循环过程中,PHP进程使用100%的CPU,但一旦中断,使用率就会下降到2%,尽管随后会立即在另一个循环中进行处理。很可能,在第一个循环中与MySQL服务器的连接非常占用资源
如果有什么不同的话,我会在本地使用MAMP PRO来完成这一切

是否有其他东西可以持续打破这个循环,我没有检查?这难道不是处理这么多记录的可行策略吗

更新
在使用批处理策略(20K增量)后,我开始在第三批前后一致地看到一个MySQL错误:
MySQL服务器已经消失了
;可能是长时间运行的无缓冲查询的症状。

如果您真的需要动态处理100K条记录,则应使用SQL进行处理,并根据需要获取结果-这将节省大量时间

但由于某些原因,你可能无法做到这一点。您总是处理语句中的所有行,所以只需使用fetchAll一次,之后就不用管MySQL了,如下所示:

$records = $query->fetchAll()
foreach ($records as record) 
{
    $obj = new Thing($record);
    /* do some processing */
    $list[] = $obj;
    $count++;
}
error_log('Processed '.$count.' records');
此外,仅选择要使用的行。
如果这不起作用,您可以尝试以下方法:。

如果您在浏览器上运行脚本,它是否返回500内部服务器错误或白色空白页?您是否在php.ini上打开了错误和警告?最近,当我试图通过php将一个巨大的数据集从xml导入mysql时,类似的事情发生在我身上。@ADASein,正如我们所说的,我正在尝试一种批处理的方法,将处理过程分为大约20K条记录。如果我确认这也不起作用,我将更新我的问题。@HddnTHA,不,这不是一个内部服务器错误,
$query->fetch()
无法在大约50K的迭代点返回记录,因此
while
循环中断。首先确保启用了错误报告,并且仍然没有记录错误如果发生这种情况,那么PHP进程会出现错误,这是a)缺陷的指示,b)不能直接修复。大多数情况下,这是由于PHP扩展中的一些错误造成的,但有时这也是核心问题。通常有变通办法。如果沿着这条路走下去,我建议仔细检查一下Thing构造函数中不是bog标准PHP的东西。使用try..catch块不捕获任何异常?