My app uses touch
on a large scale to take advantage of the template caching system of Railways is. There is a specific type of work, when I have an app, when many relationships are made between batch in many different things. Occasionally, some of these work results in cascading touch
es due to deadlock.
I can code around this code for this scenario where I often see it, but looking at it
To understand it, in a single moment on Twitter Think about two people after each other. They both click on "follow-up", as a result the relationship items are created between them and then touch
ed each of their records. If this touch differs:
- Process 1 touches user A
- Process touches user 2
- Process 1 touches user
- Process 2 touches user A
Each process is using a database transaction, hence the deadlock will occur.
Am I mistaken that this normal app could work out of my strange batch job scenario? If I am not wrong, then is there a solution? Can I move the touch
es to stay outside the transaction in some way?
Updates - More details of the data model
Follow square follow_to: followers (Last list win is ok to update_at update OK ...) , touch: True right_to: follow-up, touch: Follow the correct end @ u1 = user.find (1) @ U2 = user.fid (2) #background job1. Create! (Followers: @ U1, follow-up: @ U2) # Follow the background job 2. Create! (Followers: @ U2, Follow-up: @ u1)
Not sure What this deadlock does, but you can add pessimistic lock on both of the records, until you want to handle them, until another lock is issued, another request will be stopped, ActiveRecord
to proceed Release the lock before
User.transaction do @ u1, @ u2 = User.lock.where (id: [1,2]) # These two records are now locked, other transaction charges # this lane Can not move forward until they get out of the block. Follow! (Followers: @ U1, Follow-up: @ U2) End # LOW Ck has been issued here
Note: Passing ID: [2 , 1]
will not return them in that order, so you have to handle that situation.
Note 2: Lots of locking can affect your overall app performance, since the user model is probably a heavily used model, but I think it all depends on this It does how often it happens.
Update: This is another way that can work, follow the first model, no touch, but instead a
after_create
Follow square follow_to: follower belongs_to: follow-after_create: touch_users def touch_users # no locking and direct database update user. There (id: [follower.id, followee id] ). Update_all (updated_at :: time.now) and end
Then the controller will do a normal transaction, or not at all, because you do not need it
Follow. Create! (Followers: @ U1, follow-up: @ U2)
Note: #update_all
Active record calls back in the fire And if you have any after_update
methods, you can avoid this method.
No comments:
Post a Comment