This post originated from an RSS feed registered with Ruby Buzz
by rwdaigle.
Original Post: What's New in Edge Rails: Pessimistic Locking
Feed Title: Ryan's Scraps
Feed URL: http://feeds.feedburner.com/RyansScraps
Feed Description: Ryan Daigle's various technically inclined rants along w/ the "What's new in Edge Rails" series.
Rails has long provided optimistic locking through the use of its lock_version magic column. In a natural compliment to that functionality, edge rails now also provides pessimistic locking support:
Pessimistic locking is specified with the lock option in your standard find method:
Person.transaction do
p = Person.find(1, :lock=> true)
p.username = 'new'
p.save!
end
This will lock the person row during the course of the specified transaction and prevent updates from occuring while the object is manipulated.
You can also lock an already loaded model with the new lock! method:
person.lock!
which is equivalent to:
person.reload(:lock => true)
Optimistic vs. Pessimistic Locking
With optimistic locking a check is done on the lock_version column by the Rails framework when a row is updated to make sure that it has the same value as when the model was first read from the database. If the lock_version has changed while the object has been in memory we assume that it’s been updated underneath us and a ActiveRecord::StaleObjectError is thrown. This is easily implemented by appending a WHERE lock_version = X clause to the update SQL. If no rows are updated it means the lock_version has changed. The important thing to note here is that this protection is provided at the application level.
Pessimistic locking is functionality provided by the database that happens at the database level. When invoked it actually locks the row(s) in question so that other update requests are blocked. This is usually done with the FOR UPDATE SQL clause. The benefit of this is that you have an exclusive lock on that row so no other operations can occur and you are guaranteed the data will not change. However, this is also the big downside – everybody else is blocked! You would never want to obtain an exclusive lock on a row and then either forget about it or have it locked for an extended amount of time. When another part of your application wants to update that data no errors will be raised, it will just hang. Nasty. Basically, don’t use pessimistic locking unless you know what you’re doing and have a reliable way of releasing the lock.