INSERT INTO locks (id, lock, revision)
VALUES ('Tom', true, 1)
IF NOT EXISTS USING TTL 20;
looks like a race condition. The same problem comes up in SQL databases - you can't lock a row that doesn't exist yet. If you write, in SQL: BEGIN TRANSACTION
SELECT FROM locks WHERE id = "Tom" AND lock = true AND revision = 1;
-- if no records returned
INSERT INTO LOCKS locks (id, lock, revision) VALUES ('Tom', true, 1)
COMMIT
you have a race condition. If two threads make that identical request near-simultaneously, both get a no-find from the select, and both do the INSERT.
SELECT doesn't lock rows that don't exist.The usual solution in SQL is to use UNIQUE indices which will cause an INSERT to fail if the record about to be inserted already exists.
I ran into this reassembling SMS message fragments, where I wanted to detect that all the parts had come in. The right answer was to do an INSERT for each new fragment, then COMMIT, then do a SELECT to see if all the fragments of a message were in. Doing the SELECT first produced a race condition.