我正在运行这样的长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
将被分片。
知道可能导致此异常的原因吗?
答案 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万个文档没有问题。