2011-05-24 29 views
2

我需要在集合X中添加新文檔以獲取插入同一集合中的最後一個文檔,因爲該文檔的某些值必須影響我當前插入的文檔。Rails一個MongoDB,如何獲取插入的最後一個文檔並確保它是線程安全的?

基本上作爲一個簡單的例子,我需要做的是:

class X 
    include Mongoid::Document 
    include Mongoid::Timestamps 

    before_save :set_sum 

    def set_sum 
    self.sum = X.last.sum + self.misc 
    end 

    field :sum, :type => Integer 

    field :misc, :type => Integer 
end 

我怎樣才能知道是否有併發插入該類型的過程,不會破壞?我必須確保當self.sum = X.last.sum + self.misc計算出X.last.sum絕對代表插入到集合中的最後一個可能的文檔?

這對我的系統很重要。它需要是線程安全的。

亞歷

PS:這也需要高性能,當有藏品50K文件,它不能。如果你需要保持需要時間來獲得最後的值...

回答

1

這種行爲相當於有一個自動增量ID。 http://www.mongodb.org/display/DOCS/How+to+Make+an+Auto+Incrementing+Field 最簡潔的方法是使用一個(或多個)文檔代表當前總值的邊集合。 然後在插入新文檔之前,在您的客戶端中,執行findAndModify(),它自動更新總計並檢索當前的總文檔。 當前文檔的一部分可以是自動增量_id,因此即使存在併發插入,只要按_id進行排序,文檔就會正確排序。 唯一需要注意的是:如果您的客戶端應用程序在findAndModify和插入之前死亡,那麼您將在那裏存在差距。 無論是沒有問題,或者您需要添加額外的保護措施,如保持邊記錄。

如果你想成爲100%的安全,你還可以從2階段得到的靈感提交 http://www.mongodb.org/display/DOCS/two-phase+commit 基本上它是與跨越超過1個服務器的任何數據庫做交易的正確方法(甚至是SQL難道不幫助那裏) 最好 AG

+0

感謝tonio,你搖滾:)我會盡快挖掘 – Alex 2011-06-01 17:57:57

0

一個運行總和,這應該可以在另一個集合中的另一個文檔上完成。保持這個運行總和的最好方法是使用$inc原子操作。在計算總和時,實際上不需要執行任何讀取。

您需要將您的X文檔插入到它的集合中,然後$inc在另一個文檔上的值,用於保留X文檔中所有misc值的相同值。

注意:這仍然不是事務性的,因爲您要分別更新兩個不同集合中的兩個文檔,但它將具有高性能且完全線程安全。

有關更多信息,請查看所有MongoDB Atomic Operations

+0

好的問題是,我需要執行的計算操作涉及比簡單的總和計算複雜一點(因此我不能使用$ inc),我需要在5或6個字段? – Alex 2011-05-25 06:08:39

相關問題