Optimistic Locking assumes that a database transaction conflict is very rare to happen. It uses a version number of the record to track the changes. It raise an error when other user tries to update the record while it is lock.
usage
Just add a lock_version column to the table you want to place the lock and Rails will automatically check this column before updating the record.
Pessimistic locking assumes that database transaction conflict is very likely to happen. It locks the record until the transaction is done. If the record is currently lock and the other user make a transaction, that second transaction will wait until the lock in first transaction is release.
usage
user = User.lock.find(1) #lock the record
user.name = 'ryan'
user.save! #release the lock
or you can also use with_lock method to select and lock the record.
user = User.find(1)
user.with_lock do #lock the record
# you can run other code here.
user.name = 'ryan'
user.save!
end
- https://www.ibm.com/support/knowledgecenter/SSPK3V_7.0.0/com.ibm.swg.im.soliddb.sql.doc/doc/pessimistic.vs.optimistic.concurrency.control.html
- http://api.rubyonrails.org/classes/ActiveRecord/Locking/Optimistic.html
- http://api.rubyonrails.org/classes/ActiveRecord/Locking/Pessimistic.html
- http://thelazylog.com/understanding-locking-in-rails-activerecord/
Hey, I think this example is incorrect:
If you modify it as:
Our assumption is that
same_user.save!
would fail but it doesn't. It succeeds because locks need to be within a transaction to work the intended way. Here the lock is not within a transaction.If you change the code as:
run the above in one console then open up another console and try:
You'll find that the console hangs and the update doesn't go through until 60s have passed.