In a web application, using the InnoDB storage engine, I was unable to adequately utilise database locking in the following scenario.
There are 3 tables, I will call them aa, ar and ai.
aa holds the base records, let's say articles. ar holds information related to  each aa record and the relation between aa and ar is 1:m.
Records in ar are stored when a record from aa is read the first time. The problem is that when two requests are initiated at (nearly) the same to read a record from aa (which does not yet have its related records stored in ar), the ar records are duplicated.
Here is a pseudo code to help understand the situation:
- Read the requested - aarecord.
- Scan the - artable to find out if the given- aarecord has anything stored already. (Assume it has not.)
- Consult - aiin order to find out what is to be stored in- arfor the given- aarecord. (- aiseems somewhat irrelevant, but I found that it too has to be involved in the locking… may be wrong.)
- Insert a few rows to - ar
Here is what I want to achieve:
- Read the requested aarecord.
WITH OR WITHOUT USING A TRANSACTIONS, LOCK ar, SO ANY SUBSEQUENT REQUEST ATTEMPTING TO READ FROM ar WILL WAIT AT THIS POINT UNTIL THIS ONE FINISHES.
- Scan the - artable to find out if the given- aarecord has anything stored already. (Assume it has not.) The problem is that in case of two simultaneous requests, both find there are no records in- arfor the given- aarecord and they both proceed to insert the same rows twice. Otherwise, if there are, this sequence is interrupted and no INSERT occurs.
- Consult - aiin order to find out what is to be stored in- arfor the given- aarecord. (- aiseems somewhat irrelevant, but I found that it too has to be involved in the locking… may be wrong.)
- Insert a few rows to - ar
RELEASE THE LOCK ON ar
Seems simple enough, I was unsuccessful in avoiding the duplicates. I'm testing the simultaneous requests from a simple command in a Bash shell (using wget).
I have spent a while learning how exactly locking works with the InnoDB engine here http://dev.mysql.com/doc/refman/5.5/en/innodb-lock-modes.html and here http://dev.mysql.com/doc/refman/5.5/en/innodb-locking-reads.html and tried several ways to utilise the lock(s), still no luck.
I want the entire ar table locked (since I want to prevent INSERTs from multiple request to occur to it) causing further attempts to interact with this table to wait until the first lock is released. But there's only one mention of "entire table" being locked in the documentation (Intention Locks section in the first linked page) but that's not further discussed or I was unable to figure how to achieve it.
Could anyone point in the right direction?
 
    