2

比方說,我有以下實體和關係:檢查是否ActiveRecord的被鎖定在「更新」狀態

A<-B<-C<-D<-E 

我有同樣的A(E至d屬於A,C和B)許多勘探

我有一段代碼,看起來像這樣:

eList=E.all 
varA=eList.first.D.C.B.A 

E.transaction do 
    ...Operations that take some time... 

    varA.update_attributes(::last_update=>Time.now) 
end 

現在認爲,這個片段與線程運行。每個E實體一個線程。這意味着如果我對一個A有10個E,那麼這個片段會同時運行10個線程。

我的問題帶有線

varA.update_attributes(:last_update=>Time.now) 

當我看着我的代碼,我看到,我有這樣的:

[DEBUG] 2013/02/13 13:09:51 [66222] - abstract_adapter.rb:198 - A Update (3107.1ms) UPDATE "A" SET "updated_at" = '2013-02-13 13:09:47.932899', "last_update" = '2013-02-13 13:09:47.932209' WHERE "id" = 144 
[DEBUG] 2013/02/13 13:09:54 [48600] - abstract_adapter.rb:198 - A Update (6812.2ms) UPDATE "A" SET "updated_at" = '2013-02-13 13:09:47.218032', "last_update" = '2013-02-13 13:09:47.217421' WHERE "id" = 144 
[DEBUG] 2013/02/13 13:09:56 [66190] - abstract_adapter.rb:198 - A Update (6717.5ms) UPDATE "A" SET "updated_at" = '2013-02-13 13:09:49.328496', "last_update" = '2013-02-13 13:09:49.327777' WHERE "id" = 144 
[DEBUG] 2013/02/13 13:09:59 [66219] - abstract_adapter.rb:198 - A Update (10816.2ms) UPDATE "A" SET "updated_at" = '2013-02-13 13:09:48.236539', "last_update" = '2013-02-13 13:09:48.235895' WHERE "id" = 144 
[DEBUG] 2013/02/13 13:10:01 [66200] - abstract_adapter.rb:198 - A Update (13450.9ms) UPDATE "A" SET "updated_at" = '2013-02-13 13:09:47.584182', "last_update" = '2013-02-13 13:09:47.583467' WHERE "id" = 144 

正如你所看到的,時間運行每個查詢增加爲每個線程。第一個需要3秒,而最後一個需要13個。我假設這是因爲我正在更新相同的記錄(A.id = 144),所以記錄被鎖定,其他線程需要等待。

我的問題是,有沒有辦法在Rails 2.3中,我可以檢測到一個記錄被鎖定,因爲它正在更新,所以我可以讓其他線程跳過更新?

喜歡的東西:

if not varA.locked then varA.update_attributes(:last_update=>Time.now) end 

這是不夠好,對我來說,更新它只有一次,所以我想其他的線程來檢查它是否已經更新,繼續前進。

FWIW,我的數據庫是Postgres的9.0

回答

0

檢查一行是否在PostgreSQL的鎖定更新是一個相對複雜的過程,並儘可能我可以告訴只有在程序語言,可以捕獲SQL異常是可行的。如果ActiveRecord能夠做到這一點,我會非常驚訝。

如果您需要這樣做,您可能需要編寫存儲過程來捕獲這些異常並刪除到SQL。