假设我正在做类似的事情(来自活动记录查询指南)
Item.transaction do
i = Item.first(lock: true)
i.name = 'Jones'
i.save
end
交易结束时锁会自动释放吗?我查看了 Active Query 指南和 ActiveRecord::Locking::Pessimistic docs,但找不到明确说明锁被释放的位置。
锁定不是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/似乎表明该方法的块结构将自动解锁。