I have a website running PHP+MySQL. It is a multiuser system and most of the MySQL tables are MyISAM-based.
The following situation got me puzzled for the last few hours:
I have two (concurrent) users A,B. Both of them will do this:
- Perform a Read Operation on Table 1
- Perform a Write Operation on another Table 2 (only if the previous Read operation will return a distinct result, e.g. STATUS=”OK”)
B is a little delayed towards A.
So it will occur like this:
- User A performs a read on Table 1 and sees STATUS=”OK”.
- (User A Schedules Write on Table 2)
- User B performs a read on Table 1 and still sees STATUS=”OK”.
- User A performs Write on Table 2 (resulting in STATUS=”NOT OK” anymore)
- User B performs Write on Table 2 (assuming STATUS=”OK”)
I think I could prevent this if Reading Table 1 and Writing to Table 2 were defined as a critical section and would be executed atomically. I know this works perfectly fine in Java with threads etc., however in PHP there is no thread communication, as far as I know.
So the solution to my problem must be database-related, right?
Any ideas?
Thanks a lot!
The Right Way: Use InnoDB and transactions.
The Wrong-But-Works Way: Use the GET_LOCK() MySQL function to obtain an exclusive named lock before performing the database operations. When you’re don, release the lock with RELEASE_LOCK(). Since only one client can own a particular lock, this will ensure that there’s never more than one instance of the script in the “critical section” at the same time.
Pseudo-code: