ActiveRecord :: lock引发了什么样的异常?

时间:2011-06-10 17:19:49

标签: ruby-on-rails activerecord exception-handling locking

我正在使用锁!在我的代码中,并希望捕获锁定时抛出的异常!由于某种原因失败(例如无法获得锁定)。什么样的例外可以锁定!扔?我检查了ruby文档,但找不到具体的Exception类。

感谢。

2 个答案:

答案 0 :(得分:2)

如有疑问,请进行探测。

考虑以下一对功能:

def long_hold
  ActiveRecord::Base.transaction do
    u = User.find(220)
    u.lock!
    sleep 100.seconds
    u.email="foo@bar.com"
    u.save!
  end
end

def short_hold
  ActiveRecord::Base.transaction do
    u = User.find(220)
    u.lock!
    u.email="foo@bar.com"
    u.save!
  end
end

在我的设置(OSX 10.11,ruby 2.2.4,rails 4.2,postgres 9.5)中,在一个rails控制台中运行long_hold,然后在第二个控制台中运行short_hold,我观察{{1阻止short_hold完成;此外,使用puts来检测代码,我们看到当long_hold正在休眠时,long_hold正在等待获取锁。

假设没有关于rails控制台独立性的任何警告,这表明如果第二个进程试图锁定已经锁定的行,则不会抛出任何异常,但该进程将阻塞直到第一个完成。

答案 1 :(得分:1)

以下是locking call的来源。它调用reload,它的源代码如下:

          # File lib/active_record/base.rb, line 2333
2333:       def reload(options = nil)
2334:         clear_aggregation_cache
2335:         clear_association_cache
2336:         @attributes.update(self.class.find(self.id, options).instance_variable_get('@attributes'))
2337:         @attributes_cache = {}
2338:         self
2339:       end

所以当你调用reload(:lock => lock)时,对lock的调用确实会更新该记录的属性。

这里有很多不同的情况。您可以尝试锁定dosnt存在的记录,或锁定已在其他位置锁定的记录。你有兴趣捕捉到什么错误?