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:
- Client "Red" calculates
sysdate
- Client "Green" calculates
sysdate
- 1 hour passes
- Client "Red" updates
TimeOfLastUpdate
with oldsysdate
- Client "Green" updates
TimeOfLastUpdate
with oldsysdate
(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?