Here are a step-by-step instructions how to replicate a deadlock - works with plain UPDATE
the same way as it does with SELECT .. FOR UPDATE
:
###1. Consistent order
1. Consistent order
BEGIN;
SELECT FROM foos WHERE owner_id = 123 AND unread
ORDER BY ??? -- any deterministic order, PK would be an obvious candidate
FOR UPDATE;
UPDATE foos SET unread = false WHERE owner_id = 123 AND unread;
END;
BEGIN;
SELECT FROM foos WHERE owner_id = 123 AND unread
ORDER BY ??? -- any deterministic order, PK would be an obvious candidate
FOR UPDATE;
UPDATE foos SET unread = false WHERE owner_id = 123 AND unread;
END;
Obviously, allall potentially competing transactions have to acquire locks in the same order.
###2. Skip locked rows
2. Skip locked rows
BEGIN;
SELECT FROM foos WHERE owner_id = 123 AND unread
-- ORDER BY ??? -- optional in this case
FOR UPDATE SKIP LOCKED;
UPDATE foos SET unread = false WHERE owner_id = 123 AND unread;
END;
BEGIN;
SELECT FROM foos WHERE owner_id = 123 AND unread
-- ORDER BY ??? -- optional in this case
FOR UPDATE SKIP LOCKED;
UPDATE foos SET unread = false WHERE owner_id = 123 AND unread;
END;
###3. One at a time
3. One at a time