In my Rails code, I need to confirm that an action is only allowed if more than one specific entry is left. For this reason, I need to block updates and then perform a read. My rails code is as follows:
PaymentProfile.transaction do profiles = PaymentProfile.lock("LOCK IN SHARE MODE").where(user_id: xxx) if profiles.count > 1 #allow else #do not allow end end
In theory, this works well and blocks lines correctly. HOWEVER, if another request crosses the same code path that opens the transaction, removes the lock that I took out in another process, thereby defeating the lock target.
From MySQL docs:
Beginning a transaction also causes table locks acquired with LOCK TABLES to be released, as though you had executed UNLOCK TABLES. Beginning a transaction does not release a global read lock acquired with FLUSH TABLES WITH READ LOCK.
source share