Reputation: 5594
I have some logic in before_save
whereby (only) when some conditions are met I let the new row be created with special_number
equal to the maximum special_number in the database + 1. (If the conditions aren't met then I do something different, so I can't use auto-increments)
My worry is that two threads acting on this database at once might pick the same special_number
if the second is executed while the first is saving. Is there way to lock the database between before_save
and finishing the save, but only in some cases? I know all saves are sent in transactions, will this do the job for me?
def before_save
if things_are_just_right
# -- Issue some kind of lock?
# -- self.lock? I have no idea
# Pick new special_number
new_special = self.class.maximum('special_number') + 1
write_attribute('special_number',new_special)
else
# No need to lock in this case
write_attribute('special_number',some_other_number)
end
end
Upvotes: 0
Views: 344
Reputation: 2712
If the special number is always increasing by 1, and you cant have "gaps", and it's saved in the db- you can use select for update:
SELECT special_num FROM nums FOR UPDATE;
UPDATE nums SET special_num = special_num + 1;
You can read about it here: select for update
Note that it is locking the DB, so you may have a performance issue if you have lots of updates to taht special number.
If you dont mind having gaps in the special num (in case a transaction is failed) an easy way is to use memcahced "inc" function, as it will preform very, very fast :)
Upvotes: 1