I have a multiple processes doing some work on accounts in a single table. I have implemented a query which each process uses to lock 100 random unlocked records by setting a value in lock column and returns the locked ids.
UPDATE accounts SET locked = now() WHERE account_id in
(SELECT account_id FROM accounts
WHERE last_account_info_fetched IS NULL AND locked IS NULL
LIMIT 100
FOR UPDATE)
RETURNING account_id
And the the process which got a bunch of IDs back from the first query in another transaction does an update and unlocks the record.
UPDATE accounts SET last_account_info_fetched = ?, locked = NULL WHERE account_id = ?
The problem is that when multiple processes run the first query, it causes a deadlock. How to fix this so that each process gets a different batch of ids without deadlocks?
ERROR: deadlock detected
Detail: Process 3428 waits for AccessExclusiveLock on tuple (16865,68) of relation 10409452 of database 10221183; blocked by process 8628.
Process 8628 waits for ShareLock on transaction 27789140; blocked by process 5340.
Process 5340 waits for ShareLock on transaction 27789126; blocked by process 3428.