尽管有很长的超时,但PHP丢失了mongoDB游标

时间:2015-10-14 15:10:32

标签: php mongodb

我正在运行这样的长mongoDB查询:

foreach($xyz->find(...)->timeout(24 * 60 * 60 * 1000)->maxTimeMS(24 * 60 * 60 * 1000) as $document) {
    ...
}

但是,尽管客户端和服务器有24小时超时,但几分钟后脚本会以MongoCursorException退出:

  

localhost:27017:找不到光标集xyz

我在PHP 5.4上使用v1.6.10 mongoDB驱动程序。 DB是mongoDB 3.0.4。 PHP将连接到mongos实例,集合xyz将被分片。

知道可能导致此异常的原因吗?

3 个答案:

答案 0 :(得分:1)

我必须说,我有类似的经历,我有一个集合,我通过

$items  = $col -> find(['data' => 'OK']);
$items->timeout(-1);
$items->maxTimeMS(3600*1000);

但是经过

步行
foreach($items as $item)
{
   ///... processing
}

大约12-15分钟后,我得到同样的错误

could not find cursor over collection

在集合中,大约有150000条记录,有趣的事实是,在处理123479条记录之后总是出现错误,无论第123480条记录的内容如何,​​无论处理相应记录所花费的时间(时间)处理记录所必需的内容可能因内容而异。

由于我找不到任何错误原因,经过多次尝试改进mongo设置,包括升级PHP的驱动程序,我现在正在批处理整个过程,这可以防止丢失游标。它工作正常,但是,我想知道更清洁的解决方案。

答案 1 :(得分:1)

似乎有更多的超时并非PHP都支持。其中一个是maxIdleTimeMS

  

在删除和关闭之前,连接在池中保持空闲的最大毫秒数。

在我的情况下发生的事情是,由于数据库有时很忙,这个长时间运行的查询空闲时间太长,因此它的光标在服务器端被丢弃。

设置此参数会有所帮助,但由于它不可用,我发现解决问题的方法是减少batch size

$cursor->batchSize(-20)

在此示例中,每个批次最多在服务器和客户端之间传输20个文档。这降低了连接空闲时间过长的可能性。当然,确切的值取决于数据库的负载,处理每个文档所需的时间等。

答案 2 :(得分:0)

我有同样的问题。我曾尝试使用最新版本的两个驱动程序,

查找 方法返回游标。我不确定这个工作的方式,但这个光标没有所有的文件。需要让mongo在一段时间内完成后获得下一个ans。

我的解决方案是使用toArray的方法MongoDB\Driver\Cursor(驱动程序mongodb

这将返回包含所有文档的数组。我有一个批处理可以处理超过10万个文档没有问题。