tags:

views:

40

answers:

4

I have a web service (xmlrpc service to be exact) that handles among other things writing data into the database. Here's the scenario:

I often receive requests to either update or insert a record. What I would do is this:

  1. If the record already exists, append to the record,
  2. If not, create a new record

The issue is that there are certain times I would get a 'burst' of requests, which spawns several apache threads to handle the request. These 'bursts' would come within less than milliseconds of each other. I now have several threads performing #1 and #2. Often two threads would would 'pass' number #1 and actually create two duplicate records (except for the primary key).

I'd like to use some locking mechanism to prevent other threads from accessing the table while the other thread finishes its work. I'm just afraid of using it because if something happens I don't want to leave the table locked.

  • UPDATE: The table already has a primary key. The ideal situation should be that the first thread should create the record if it doesn't exist, then once the second thread comes in, it won't create the another record, but just update the record that was already created. It's almost as though I'd like to make the threads form a single-file line.

Is there a solid way of handling this? I'm open to using locks if I can do it properly.

Thanks,

+1  A: 

If you add a unique index on your table, the second insert will fail. Thus, all logic will be done by database server, and all you need is just to display an error to the user... Also, in such scenario, you don't have to lock table[s] during insert operations.

a1ex07
+5  A: 

Add a unique or primary index and use:

INSERT INTO table (..) VALUES (...) ON DUPLICATE KEY UPDATE .....
Wrikken
The table already has a primary key. In my situation, two records would be identical, except the primary key being 1 more than the previous. The ideal situation should be that the first thread should create the record if it doesn't exist, then once the second thread comes in, it won't create the another record, but just update the record that was already created. It's almost as though I'd like to make the threads form a single-file line. :)
Ed Gl
How can you see it's a duplicate? Those columns you're about to mention, add a UNIQUE index to them. Keep in mind a UNIQUE index can span more then one column. Then the ON DUPLICATE KEY UPDATE could do exactly that.
Wrikken
Ed, that doesnt make sense. Either you have a way to uniquely identify the row (other that an autoincrementing key) and then Wrikkens method will work. Or, if you dont, you can not talk about "the row" since there is no unique name for it and therefor no way to update it.
Serbaut
+1  A: 

You can put numerous steps that forms an atomic operation in a TRANSACTION

Mike Gleason jr Couturier
A: 

If you truly want to serialize your process, you can grab a Lock Tables tablename Write at the start of your service, and Unlock Tables when done.

If you are using Innodb and transactions, you have to perform the Lock Tables after the start of the transaction.

I am not advocating this method, as there is usually a better way of handling, however if you need a quick and dirty solution, this will work with a minimal amount of code changes.

Gary
This is what I was thinking too, but let me get all the opinions of others to see if there was a better way. :) Seems like the ON DUPLICATE KEY would be the way to go.
Ed Gl