我有一個簡單的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你可以得到這種行爲,但我認爲兩個最安全的將確保寫入實際發生之前繼續。
應用程序的時間戳輸出只能證明操作是按順序執行的,但並不能證明執行計數查詢時,MongoDB應該已經完成了插入操作。另請注意,暫停並不是處理異步調用的可靠方法。你真的需要回調和控制流的形式。然而,2秒的等待足夠時間執行3次插入,因爲典型大小的文檔上的插入應該在幾ms或更短的時間內發生。你使用哪種Java驅動程序?您是使用社區異步驅動程序還是MongoDB本機驅動程序? –
我通過casbah使用java驅動程序2.11.2。因爲寫入發生在異步邏輯路徑的深處,而讀取是測試套件(scalatest)的一部分,所以需要暫停。生產代碼不依賴於暫停......測試只需要等待足夠的時間來合理地確保所發生的一切。我的頭腦是,我認爲SAFE或FSYNC_SAFE WriteConcern應該確保在返回控制之前發生寫入,理論上說,打印時間戳時應該完成寫操作。這些結果讓我懷疑我對這些WriteConcerns的理解。 – Greg
編寫關注安全確保寫入將錯誤信息返回給客戶端,這可能與網絡,欺騙密鑰和其他錯誤等約束違規相關(http://docs.mongodb.org/manual/core/write-concern/)。這與「忘卻遺忘」未確認的寫法相反。 Fsync意味着只有在寫入數據文件後,MongoDB纔會迴應錯誤信息。通常,MongoDB只是寫入虛擬內存(mem映射文件),並且在典型的代碼路徑下,異步刷新數據文件和/或日誌。 –