假设我有以下实体和关系:
A<-B<-C<-D<-E
对于同一个 A,我有很多 E(E 通过 D、C 和 B 属于 A)
我有一个看起来像这样的代码片段:
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