2011-02-06 60 views
1

我想在我的MongoDB數據庫中使用Morphia遍歷所有行(「文檔」?)。偶爾我得到以下堆棧跟蹤:Morphia/MongoDB:不能做getmore

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 
    } 

嗎啡錯誤? 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) 

回答

1

剛剛遇到同樣的問題,而迭代通過一個非常大的查詢。我發現這個嗎啡的bug彙報了2011年3月21日:

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

問題251:啓用/禁用超時做什麼它說

相反的問題說,這將是1.0版固定。新的API disableCursorTimeout()暴露在1.00-SNAPHSHOT中。我正在運行long測試以查看它是否修復了此問題。

1

正如你可以看到在這個thread MongoDB的一定時間後釋放光標。一種可能的解決方案可能是模擬批量迭代,並在循環中更新光標。

1

這是實際的代碼嗎?該代碼似乎不太可能產生該異常。遊標在閒置10分鐘後超時。像這樣的緊密循環似乎是不可能的。

您可以使用datastore.createQuery(App.class).disableTimeout()...來禁用Morphia中的遊標超時。您也可以使用datastore.createQuery(App.class).fetchEmptyEntities(),如果你只是想@Id現場填寫

而且,也沒有必要顯式調用fetch()如果你只是想用迭代器像一個for循環。當您想將迭代器存儲在一個變量中並在多個位置使用它時,只需要獲取fetch,而不是在單個for循環中。

+0

我試圖在問我的問題時儘可能簡化代碼,所以你是正確的,我已經遺漏了可能有用的信息。 「做東西與應用程序」會發生什麼:查詢Web服務並將結果保存到磁盤上的文件。這通常以毫秒爲單位執行,但我會在循環中添加一些時間檢查,並查看是否沒有導致超時的異常行爲。謝謝。 –

+0

剛做了幾輪測試,發現超時在迭代過程中進行了45分鐘,這是可重複的。請注意,每次遍歷我的迭代循環通常<1秒,所以它似乎是整個迭代過程的超時,而不是每次調用Iterator.next()之間的延遲。 –

+0

這不是那麼簡單。遊標,迭代器從服務器批量獲取數據;每個對next()的調用可能會或可能不會(批量大小可能爲200+以上)必須與服務器通話。你有沒有嘗試disableTimeout選項? –