2010-03-04 67 views
2

我正在研究一個應用程序,其中一個模塊訪問日誌(ActiveRecord模型)以在執行的多個點增加各種值。問題是腳本可能需要幾秒鐘,同一腳本的其他實例可能會同時運行。在Rails中更新/遞增值時的數據完整性

我看到的是,雖然腳本正確地完成並且所有數據都被計算在內,但這些值永遠都是正確的。這很可能是因爲在腳本到達更新值的時候,列的讀取值(已遞增)已經過時。

這些值是正確的,如果我強迫它一次只有一個模塊實例,但出於性能原因,我不能繼續這樣做。

目前,我已經嘗試通過在交易查詢記錄數據庫中每個增量語句之前,像這樣來解決問題,其中column是列的象徵,value爲1或更高版本:

Log.transaction do 
    log = Log.find(@log_id) 
    log.update_attribute(column, log.send(column) + value) 
end 

但是,它仍然不會給我準確的數字。我想緩存參與,我想我可以嘗試像:

Log.transaction do 
    uncached do 
    log = Log.find(@log_id) 
    log.update_attribute(column, log.send(column) + value) 
    end 
end 

但可以肯定,我不能成爲第一個遇到這個問題,所以我想知道是否有更好的執行/解決我的問題?

回答

3

ActiveRecord提供了update_counters方法。您可以更改您的代碼,如下所示:

Log.update_counters @log_id, column.to_sym => value 
+0

這看起來像一個很好的選擇。不能相信我錯過了那一個。將測試並看看它是如何工作的。 – vonconrad 2010-03-04 09:02:51

+0

如果兩個腳本在重疊事務中調用'update_counters',則仍然存在爭用條件;一個會覆蓋另一個的'更新'。如果你想要真正的順序性,你必須鎖定該行('Model.find(...,:lock => true)'),或者使用外部的例如文件系統或IPC鎖。 – vladr 2010-03-04 20:31:33