MongoDB - PHP - MongoCursorException'未找到游标'

时间:2011-07-24 07:18:44

标签: php mongodb mongodb-php

我有2个集合:A(3.8M docs)和B(1.7M docs)

我有一个PHP脚本,我从shell运行:

  1. 循环遍历A
  2. 中的每条记录
  3. ~60%的时间,它在B上执行findOne(使用_id)
  4. 做一些基本的数学运算,创建一个php数组
  5. 完成a中所有文档的循环后:

    4)循环遍历php数组

    5)upsert into collection C

    在(1)期间,我一直得到:PHP致命错误:未捕获异常'MongoCursorException',消息'找不到游标' 处理的最后一项是#8187 of 3872494。

    real    1m25.478s
    user    0m0.076s
    sys     0m0.064s
    

    再次运行它,代码没有变化,在#19826/3872495项目中抛出异常

    real    3m19.144s
    user    0m0.120s
    sys     0m0.072s
    

    再次,#8181/387249

    real    1m31.110s
    user    0m0.036s
    sys     0m0.048s
    

    是的,我意识到我可以(并且可能应该)捕获异常...但是......为什么它甚至被抛出?特别是在进入数据库的这种不同的经过时间/深度。

    如果有帮助,我的设置是3节点副本集(2 + arb)。我让二级离线并尝试了主要的运行。相同的结果(处理的结果数量和次数不同,但总是抛出Cursor Not Found异常)。

3 个答案:

答案 0 :(得分:10)

  

是的,我意识到我可以(也可能应该)抓住异常......

是的,这绝对是第一件事。异常发生有几十个合理的原因?当主要离线并无法访问时,您认为会发生什么?

  

......为什么甚至被抛出?

有几个可能的原因,但让我们直截了当地看看你看到的错误代码。

  • 官方PHP文档为here
  • 从该页面引用:驱动程序试图从数据库中获取更多结果,但数据库没有查询记录。这通常意味着光标在服务器端超时......

MongoDB PHP驱动程序有两种不同的超时:

  • 连接超时
  • 光标超时

你正在点击游标超时。您可以连接到数据库,但查询“时间不多了”。

可能的修复:

  1. 延长光标timeout。或者您可以将其设置为零并使其永久持续。
  2. 分批完成这项工作。从A中获取前1000个_ids,处理它们,然后标记您已经这样做了。然后获得比上一次运行更大的_ids,依此类推。
  3. 我会建议#2以及处理异常。即使这些不能完全解决问题,它也可以帮助您隔离和缓解问题。

答案 1 :(得分:4)

我知道它已经晚了,这可能不是你的解决方案,但你可以尝试使用immortal()。正如盖茨副总裁所说,this page描述了例外。

  

驱动程序试图从数据库中获取更多结果,但数据库没有查询记录。这通常意味着游标在服务器端超时:在几分钟不活动后,数据库将终止游标(有关防止这种情况的信息,请参阅MongoCursor::immortal()。)

我想我会发布其他人到达此页面的完整描述,因为timeout()和immortal()是不同的。 timeout()设置等待响应的时间。 immortal()拒绝光标因不活动而死亡。

答案 2 :(得分:0)

这可能是内存限制问题。尝试提供更多内存并查看结果是否有所不同,您可以使用-d选项:php -d memory_limit = 256M yourscript.php

这是很多文档,听起来你正在制作一大堆对象。还有各种各样的php函数,比如memory_get_usage(),可用于在运行时分析内存分配,以及调试xdebug或zend提供的扩展。