6

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

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

  1. 循环 A 中的每条记录
  2. 约 60% 的时间,它在 B 上执行 findOne(使用 _id)
  3. 做一些基本的数学运算,创建一个 php 数组

一旦 a 中所有文档的循环完成:

4) 循环遍历 php 数组

5) 插入集合 C

在 (1) 期间,我一直得到: PHP 致命错误:未捕获的异常 'MongoCursorException' 和消息 'Cursor not found' 最后处理的项目是 3872494 中的 #8187。

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 异常)。

4

3 回答 3

10

是的,我意识到我可以(并且可能应该)捕获异常......

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

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

有几个潜在的原因,但让我们直接切入您看到的错误代码。

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

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

  • 连接超时
  • 光标超时

您正在遇到光标超时。您可以连接到数据库,但您的查询“超时”。

可能的修复:

  1. 延长游标超时。或者您可以将其设置为零并使其永久存在。
  2. 分批完成这项工作。从 A获取前 1000 个_ids,处理它们,然后标记你已经这样做了。_ids然后获得比上次运行大的下一个 1000 ,依此类推。

我会建议#2以及处理异常。即使这些不能完全解决问题,它也会帮助您隔离和缓解问题。

于 2011-07-24T07:51:52.737 回答
4

我知道已经很晚了,这可能不是您的解决方案,但您可以尝试使用 immortal()。正如盖茨副总裁所指出的,此页面描述了例外情况。

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

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

于 2011-10-18T06:40:09.350 回答
0

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

那是很多文档,听起来你正在制作一个相当大的对象数组。还有各种 php 函数,例如 memory_get_usage(),您可以使用它来分析运行时的内存分配以及调试扩展,例如 xdebug 或 zend 提供的功能。

于 2011-07-24T07:49:27.393 回答