How to ensure MySQL lock registration order in Rails
We are using Rails 4.1 and a has_many model.
Model X has_many Y
Y can be updated and then X can be updated via callbacks (increase the version field, modified_at, etc.)
X can also be updated by itself.
This causes deadlocks inside MySQL as one transaction will lock Y1 and then lock X1, while another transaction will lock X1 and then lock Y1.
This is easy to fix by requiring a minimum of a SELECT ... FOR UPDATE
to store X before updating Y.
How do I do this in Rails? Or is there an even better solution?
I'm considering trying to ensure that I have a transaction in the before_update callback on Y and then acquiring the lock on X, but I'm not sure if this will work well with Rails.
source to share
Have you tried using block transaction
?
So, for example, you can define your own method save_with_transaction
like this:
class X < ActiveRecord::Base
def save_with_transaction
transaction do
# multiple save, update, delete calls here ...
end
end
end
More documentation on transactions in ActiveRecord here
source to share