2016-05-17 177 views
2

我的服務器應用程序(使用node.js,mongodb,mongoose)有一個文檔集合,對於這兩個文檔,兩個客戶端應用程序不能同時修改它們而不看到彼此的修改。防止併發訪問Mongoose中的文檔

爲了防止出現這種情況,我添加了一個簡單的文檔版本控制系統:在架構上檢查文檔的版本是否有效(即不高於客戶端上次讀取的版本)。乍一看,它工作正常:

// Validate version number 
UserSchema.pre("save", function(next) { 
    var user = this 

    user.constructor.findById(user._id, function(err, userCurrent) { // userCurrent is the user that is currently in the db 
    if (err) return next(err) 
    if (userCurrent == null) return next() 

    if(userCurrent.docVersion > user.docVersion) { 
     return next(new Error("document was modified by someone else")) 
    } else { 
     user.docVersion = user.docVersion + 1 
     return next() 
    } 
    }) 
}) 

的問題如下:

當一個用戶文件被兩個客戶端應用程序保存在同一時間,是有可能,這些交織前鉤之間和實際的保存操作?我的意思是下面的,想象的時間從左至右和v爲版本號(由保存持久化):

App1: findById(pre)[v:1]         save[v->2] 
App2:      findById(pre)[v:1] save[v->2] 

在應用1所得節省的東西,已經被同時修改(通過應用2),它無法注意到它已被修改。 App2的更新完全丟失。

我的問題可能歸結爲:Mongoose pre-hook和save方法是否在一個原子步驟中發生?

如果不是,你能否給我一個關於如何解決這個問題的建議,以避免更新丟失?

謝謝!

回答

2

MongoDB有findAndModify對於單個匹配的文檔,它是一個原子操作。

貓鼬有使用這種方法的各種方法,我認爲他們會滿足你的使用情況:

另一個解決方案(貓鼬本身就是我們的一員es以及它的own document versioning)是使用Update Document if Current模式。

+0

謝謝你,那是有效的。尤其是您所建議的模式,因爲它允許在嘗試更新之前進行文檔版本檢查。 – Zxifer