when is a pessimistic lock released in rails?
Assuming I'm doing something like this (from the Active Record Querying guide)
Item.transaction do
i = Item.first(:lock => true)
i.name = 'Jones'
i.save
end
Is the lock automatically released at the开发者_StackOverflow end of the transaction? I've looked at the Active Query guide and the ActiveRecord::Locking::Pessimistic docs, and couldn't find where it explicitly says where the lock is released.
Locking is not a function of rails, it is just adding the lock statement to the query, which will vary depending on the database that you are using. Pessimistic Locking takes a "pessimistic" view in thinking that every query is subject to corruption. So it is going to lock selected rows until you are finished with the transaction. so Lock > query > unlock. While these are fairly consistent database to database, it might be good to read up on the database documentation that you using for any database-specific things you should know.
Here is a good thread on optimistic vs. pessimistic locking that explains it better than I can. Optimistic vs. Pessimistic locking
Yes, the lock automatically released at the end of the transaction because this kind of lock is applicable to transactions only. It does not make sense to lock the record this way (pessimistic lock) outside the transaction.
Pessimistic locks are enforced on DB level.
Below is a description with examples for mysql: http://dev.mysql.com/doc/refman/5.0/en/innodb-lock-modes.html
I acknowledged the problem with pessimistic lock within transaction during rspec tests. For some reason on different systems (I found this because of CI failed to run spec) record is still locked and cannot be fetched.
So code and rspec example are below.
class FooBar
def foo
Model.with_lock do
model.update(bar: "baz")
end
end
end
red example
it "updates with lock" do
expect { Foobar.foo }.to change { model.reload.bar }.to("baz")
end
but correct green example should look like this
it "updates with lock" do
Foobar.foo
expect(model.reload.bar).to eq("baz")
end
I believe you'll want an "ensure" block to be certain the lock is released.
http://ruby-doc.org/core/classes/Mutex.src/M000916.html has:
def synchronize
lock
begin
yield
ensure
unlock
end
end
http://yehudakatz.com/2010/02/07/the-building-blocks-of-ruby/ seems to suggest, however, that the block structure of that method will automatically unlock.
精彩评论