简体   繁体   中英

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 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.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM