1

I have a distributed application that uses the database to synchronize clients. Clients will attempt to update a record, but will only do so if no other client has done so in the past 1 hour.


Here's the minified code and the dilemma:

Say one client tries to update a field to "Red" (checking that no one else has updated it within the past hour):

UPDATE mytesttable
SET Status = 'Red',
    TimeOfLastUpdate = sysdate 
WHERE TimeOfLastUpdate < sysdate-1/24

And, at the same time, another client tries to update it to "Green" (checking that no one else has updated it within the past hour):

UPDATE mytesttable
SET Status = 'Green',
    TimeOfLastUpdate = sysdate 
WHERE TimeOfLastUpdate < sysdate-1/24

Can I assume that only one client will succeed in updating the row?


Here's why I think the answer is "no":

Since Oracle must resolve sysdate before it acquires the row-level update lock (since it must use it to find the row in the first place), it appears there is a race condition:

  1. Client "Red" calculates sysdate
  2. Client "Green" calculates sysdate
  3. 1 hour passes
  4. Client "Red" updates TimeOfLastUpdate with old sysdate
  5. Client "Green" updates TimeOfLastUpdate with old sysdate (thus updating twice)

Am I right in identifying this as a race condition? If not, what am I missing?

If so, is there an efficient, more reliable solution to this problem?

Jay Sullivan
  • 17,332
  • 11
  • 62
  • 86
  • 1
    While not exactly your question, I think the accepted answer would be my advice to you as well. Use a sequence if you absolutely must ensure that only one updates it. http://stackoverflow.com/questions/8498169/race-condition-between-select-and-update – Uncle Iroh Apr 16 '13 at 19:32

2 Answers2

0

As per my understanding these kind scenarios should be handled at the code level, rather leaving it to backend. Synchronization can be handled easily during programming. Try to implement that way.

Madhusudan Joshi
  • 4,438
  • 3
  • 26
  • 42
  • How would you recommend accomplishing this? I don't see how it would be handled "easily". Keep in mind this is a distributed application, which means there are multiple clients and their clocks are not necessarily synchronized. – Jay Sullivan Apr 17 '13 at 17:14
  • You are absolutely right that it won't be easy to handle in such a distributed application environment. Hers's what i am thinking, leaving this synchronization of updating to data base level won't be much effective than programming level. There should be some intermediate interface which subscribed to different clients and do the synchronization. – Madhusudan Joshi Apr 18 '13 at 06:35
  • It sounds like you're suggesting I create a web service that all clients point to. Maintaining a web server just for this introduces a lot of future maintenance. – Jay Sullivan Apr 19 '13 at 13:17
0

The solution that worked for me: double update. For example:

UPDATE mytesttable
SET TimeOfLastUpdate = TimeOfLastUpdate 
WHERE TimeOfLastUpdate < sysdate-1/24

UPDATE mytesttable
SET Status = 'Red',
    TimeOfLastUpdate = sysdate 
WHERE TimeOfLastUpdate < sysdate-1/24

COMMIT;

(similar code for 'Green')

The first update doesn't change anything, but it grabs a lock on the row, which won't be released until commit is called.

The second update updates the row with a sysdate that is guaranteed to be greater than or equal to the time that the lock was acquired, thus preventing race conditions. (Unless sysdate were to go backwards in time.)

Jay Sullivan
  • 17,332
  • 11
  • 62
  • 86