ActiveRecord 中的悲观锁什么时候释放?

问题描述 投票:0回答:4

假设我正在做类似的事情(来自活动记录查询指南

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

交易结束时锁会自动释放吗?我查看了 Active Query 指南和 ActiveRecord::Locking::Pessimistic docs,但找不到明确说明锁被释放的位置。

locking rails-activerecord pessimistic
4个回答
28
投票

锁定不是rails的功能,它只是在查询中添加锁定语句,这会根据您使用的数据库而有所不同。 悲观锁定采取“悲观”观点,认为每个查询都会受到损坏。 因此,它将锁定选定的行,直到您完成事务。 所以锁定>查询>解锁。 虽然这些数据库与数据库之间相当一致,但最好阅读您使用的数据库文档来了解您应该了解的任何特定于数据库的内容。

这是一个关于乐观锁定与悲观锁定的好帖子,它比我能更好地解释它。 乐观锁定与悲观锁定


7
投票

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

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

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


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 "updates with lock" do
  Foobar.foo
  expect(model.reload.bar).to eq("baz")
end

-3
投票

我相信您会需要一个“确保”块来确定锁已释放。

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/似乎表明该方法的块结构将自动解锁。

© www.soinside.com 2019 - 2024. All rights reserved.