2013-08-02 62 views
0

我有一個簡單的mongo應用程序,它恰好是異步的(使用Akka)。 我給一個演員發送一條消息,演員又將3條記錄寫入數據庫。 我正在使用WriteConcern.SAFE,因爲我想確保寫入發生(也嘗試WriteConcern.FSYNC_SAFE)。MongoDB WriteConcern Java驅動程序

我暫停一秒鐘,讓寫作發生然後做一個閱讀 - 什麼都不要。

所以我寫的代碼可能是:

collection.save(myObj, WriteConcern.SAFE) 
println("--1--") 
collection.save(myObj, WriteConcern.SAFE) 
println("--2--") 
collection.save(myObj, WriteConcern.SAFE) 
println("--3--") 

然後在我的測試代碼(演員外運行 - 在另一個線程)我打印出來的記錄#我發現:

println(collection.findAll(...)) 

我的輸出是這樣的:

--1-- 
--2-- 
--3-- 
(pauses) 
0 

事實上,如果我看在我看不出有任何記錄的數據庫。 有時我實際上看到數據和測試工作。異步代碼可能會非常棘手,在寫入之前可能會測試代碼,所以我也嘗試打印出時間戳,以確保它們按照所呈現的順序執行 - 它們是。數據應該在那裏。下面的示例輸出帶有時間戳:

Saved: brand_1/dev 1375486024040 
Saved: brand_1/dev2 1375486024156 
Saved: brand_1/dev3 1375486024261 
         1375486026593 0 found 

因此,3次保存在嘗試讀取之前已經明顯發生了(應該寫入)整整2秒。

我知道更自由的WriteConcerns你可以得到這種行爲,但我認爲兩個最安全的將確保寫入實際發生之前繼續。

+0

應用程序的時間戳輸出只能證明操作是按順序執行的,但並不能證明執行計數查詢時,MongoDB應該已經完成​​了插入操作。另請注意,暫停並不是處理異步調用的可靠方法。你真的需要回調和控制流的形式。然而,2秒的等待足夠時間執行3次插入,因爲典型大小的文檔上的插入應該在幾ms或更短的時間內發生。你使用哪種Java驅動程序?您是使用社區異步驅動程序還是MongoDB本機驅動程序? –

+0

我通過casbah使用java驅動程序2.11.2。因爲寫入發生在異步邏輯路徑的深處,而讀取是測試套件(scalatest)的一部分,所以需要暫停。生產代碼不依賴於暫停......測試只需要等待足夠的時間來合理地確保所發生的一切。我的頭腦是,我認爲SAFE或FSYNC_SAFE WriteConcern應該確保在返回控制之前發生寫入,理論上說,打印時間戳時應該完成寫操作。這些結果讓我懷疑我對這些WriteConcerns的理解。 – Greg

+0

編寫關注安全確保寫入將錯誤信息返回給客戶端,這可能與網絡,欺騙密鑰和其他錯誤等約束違規相關(http://docs.mongodb.org/manual/core/write-concern/)。這與「忘卻遺忘」未確認的寫法相反。 Fsync意味着只有在寫入數據文件後,MongoDB纔會迴應錯誤信息。通常,MongoDB只是寫入虛擬內存(mem映射文件),並且在典型的代碼路徑下,異步刷新數據文件和/或日誌。 –

回答

0

微妙但簡單的問題。我正在使用def來創建我的連接......然後我再次調用兩次,就好像它是一個val。所以我實際上有兩個不同的作家,以便解釋我的結果有時會出現差異。重構爲val,全都是可預測的。 agonizing識別,易於理解/修復。