【问题标题】:Morphia/MongoDB: can't do getmoreMorphia/MongoDB:不能做 getmore
【发布时间】:2011-02-06 18:36:34
【问题描述】:

我正在尝试使用 Morphia 遍历 MongoDB 数据库中的所有行(“文档”?)。有时我会得到以下堆栈跟踪:

com.mongodb.MongoInternalException: can't do getmore
    at com.mongodb.DBApiLayer$Result._advance(DBApiLayer.java:378)
    at com.mongodb.DBApiLayer$Result.hasNext(DBApiLayer.java:356)
    at com.mongodb.DBCursor._hasNext(DBCursor.java:436)
    at com.mongodb.DBCursor.hasNext(DBCursor.java:456)
    at com.google.code.morphia.query.MorphiaIterator.hasNext(MorphiaIterator.java:40)
    at 

在 MongoDB 日志文件中,我看到以下内容:

$ grep "cursorid not found" output.log 
Sun Feb  6 12:14:35 [conn13] getMore: cursorid not found App 2079575931792020691
Sun Feb  6 12:44:17 [conn19] getMore: cursorid not found App 8364953818630631317
Sun Feb  6 13:08:42 [conn20] getMore: cursorid not found App 7142256996888968009

我的迭代代码非常简单:

    for (App app : datastore.createQuery(App.class).fetch())
    {
        log.info("app: " + app.getId());
        // do stuff with app
    }

Morphia 虫子? MongoDB 错误?我的错误?

更新:

我在 glassfish 日志中也看到了这一点:

[#|2011-02-16T15:39:58.029+0000|WARNING|glassfish3.0.1|com.mongodb.TRACE|_ThreadID=28;_ThreadName=Thread-1;|The log message is null.
java.lang.NullPointerException
    at com.mongodb.DBApiLayer._cleanCursors(DBApiLayer.java:113)
    at com.mongodb.DBApiLayer$DBCleanerThread.run(DBApiLayer.java:494)
    at java.lang.Thread.run(Thread.java:662)

【问题讨论】:

    标签: java mongodb morphia


    【解决方案1】:

    在迭代一个非常大的查询时遇到了同样的问题。我发现了这个 Morphia 错误,报告于 2011 年 3 月 21 日:

    http://code.google.com/p/morphia/issues/detail?id=251

    问题 251:启用/禁用超时与它所说的相反

    该问题表示将在 1.0 版中修复。新 API disableCursorTimeout() 在 1.00-SNAPHSHOT 中公开。我正在运行 long 测试,看看它是否能解决问题。

    【讨论】:

      【解决方案2】:

      正如您在thread 中看到的那样,MongoDB 在一定时间后释放游标。一种可能的解决方案可能是模拟批量迭代并在循环的和处更新光标。

      【讨论】:

        【解决方案3】:

        那是实际的代码吗?该代码似乎不太可能产生该异常。光标在 10 分钟不活动后超时。像这样的紧密循环似乎是不可能的。

        您可以使用datastore.createQuery(App.class).disableTimeout()... 来禁用 Morphia 中的光标超时。如果您只想填写@Id 字段,也可以使用datastore.createQuery(App.class).fetchEmptyEntities()

        此外,如果您只想在这样的 for 循环中使用迭代器,则无需显式调用 fetch();当您想将迭代器存储在一个变量中并在多个地方使用它而不是在单个 for 循环中时,才需要 fetch。

        【讨论】:

        • 我在提出问题时尝试尽可能简化代码,所以您说得对,我遗漏了可能有用的信息。 “用应用程序做事”中发生的事情是:查询 Web 服务并将结果保存到磁盘上的文件中。这通常以毫秒为单位执行,但我会在循环中添加一些时间检查,看看是否存在导致超时的异常行为。谢谢。
        • 刚做了几轮测试,发现超时发生在迭代过程的45分钟,这是可重复的。请注意,每次通过我的迭代循环通常小于 1 秒,因此这似乎是整个迭代过程的超时,而不是每次调用 Iterator.next() 之间的延迟。
        • 没那么简单。游标,迭代器,正在从服务器批量取数据;对 next() 的每次调用可能会或实际上不会(批量大小可以是 200+),必须与服务器通信。您是否尝试过 disableTimeout 选项?
        • disableTimeout() 似乎正在工作。在我完成迭代器之后,我需要做些什么特别的事情来释放它,现在超时被禁用了吗?
        • 从头开始 - 它仍然失败,即使使用 disableTimeout。
        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2017-10-30
        • 2011-07-23
        • 2012-08-02
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多