17

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

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

锁是在事务结束时自动释放的吗?我查看了 Active Query 指南和ActiveRecord::Locking::Pessimistic 文档,但找不到明确说明释放锁的位置。

4

4 回答 4

25

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

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

于 2010-07-08T17:10:29.727 回答
5

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

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

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

于 2010-12-17T16:13:02.363 回答
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
于 2019-07-01T14:24:28.790 回答
-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/似乎暗示该方法的块结构将自动解锁。

于 2010-07-08T16:13:36.050 回答