假设我正在做这样的事情(来自Active Record Querying guide)
Item.transaction do
i = Item.first(:lock => true)
i.name = 'Jones'
i.save
end
锁是在事务结束时自动释放的吗?我查看了 Active Query 指南和ActiveRecord::Locking::Pessimistic 文档,但找不到明确说明释放锁的位置。
假设我正在做这样的事情(来自Active Record Querying guide)
Item.transaction do
i = Item.first(:lock => true)
i.name = 'Jones'
i.save
end
锁是在事务结束时自动释放的吗?我查看了 Active Query 指南和ActiveRecord::Locking::Pessimistic 文档,但找不到明确说明释放锁的位置。
锁定不是 rails 的功能,它只是将锁定语句添加到查询中,这将根据您使用的数据库而有所不同。悲观锁定采取“悲观”的观点认为每个查询都受到损坏。所以它将锁定选定的行,直到您完成事务。所以锁定>查询>解锁。虽然这些是数据库之间相当一致的数据库,但最好阅读您使用的数据库文档来了解您应该知道的任何特定于数据库的事情。
这是一个关于乐观与悲观锁定的好帖子,它比我能更好地解释它。 乐观与悲观锁定
是的,锁在事务结束时自动释放,因为这种锁只适用于事务。在事务之外以这种方式锁定记录(悲观锁定)是没有意义的。
悲观锁在数据库级别强制执行。
以下是 mysql 示例的描述:http: //dev.mysql.com/doc/refman/5.0/en/innodb-lock-modes.html
在 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
我相信你会想要一个“确保”块来确定锁被释放。
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/似乎暗示该方法的块结构将自动解锁。