什么时候在铁轨上发布一个悲观的锁?

时间:2010-07-08 15:57:37

标签: ruby-on-rails locking pessimistic

假设我正在做这样的事情(来自Active Record Querying guide

Item.transaction do  
  i = Item.first(:lock => true)  
  i.name = 'Jones'  
  i.save 
end 

在交易结束时锁是否自动释放?我查看了“活动查询”指南和ActiveRecord::Locking::Pessimistic docs,但无法找到明确说明锁定释放位置的位置。

4 个答案:

答案 0 :(得分:24)

锁定不是rails的功能,它只是将lock语句添加到查询中,这将根据您使用的数据库而有所不同。 Pessimistic Locking认为每个查询都会受到腐败,因此采取“悲观”的观点。因此,在您完成事务之前,它将锁定所选行。所以锁定>查询>开锁。虽然这些数据库与数据库是相当一致的,但是阅读您用于任何您应该知道的特定于数据库的事物的数据库文档可能会很好。

这是一个关于乐观与悲观锁定的好线程,它比我能更好地解释它。 Optimistic vs. Pessimistic locking

答案 1 :(得分:5)

是的,锁在交易结束时自动释放,因为这种锁只适用于交易。在事务之外以这种方式锁定记录(悲观锁定)是没有意义的。

在数据库级别强制执行悲观锁定。

以下是mysql示例的说明: http://dev.mysql.com/doc/refman/5.0/en/innodb-lock-modes.html

答案 2 :(得分:0)

我承认在rspec测试期间事务内的悲观锁定问题。 出于某种原因,在不同的系统上(我发现这是由于CI无法运行规范),记录仍然被锁定并且无法获取。

下面是代码和rspec示例。

class FooBar
  def foo
    Model.with_lock do
      model.update(bar: "baz")
    end
  end
end

红色示例

it "updates with lock" do
  expect { Foobar.foo }.to change { model.reload.bar }.to("baz")
end

正确 绿色示例应如下图所示

it do "updates with lock" do
  Foobar.foo
  expect(model.reload.bar).to eq("baz")
end

答案 3 :(得分:-2)

我相信你会想要一个“确保”阻止来确定释放锁定。

http://ruby-doc.org/core/classes/Mutex.src/M000916.html有:

  def synchronize
    lock
    begin
      yield
    ensure
      unlock
    end
  end
然而,

http://yehudakatz.com/2010/02/07/the-building-blocks-of-ruby/似乎暗示该方法的块结构将自动解锁。