BEGIN;
LOCK TABLE slots IN ACCESS EXCLUSIVE MODE;
UPDATE slots SET job_name = '111' WHERE id IN (SELECT id FROM slots WHERE job_name IS NULL LIMIT 1) RETURNING *;
COMMIT;
Zdá se, že to funguje v Read Committed. Je pouze sql (stejný jako váš kód) a lze jej spustit v jednom volání (rychlejší).
@Seth Robertson:Bez LOCK TABLE a bez smyčky while to není bezpečné.
Pokud existuje transakce A a transakce B současně:A vybere první řádek a B vybere první řádek. A zamkne a aktualizuje řádek, B musí počkat, dokud A nepotvrdí. Potom B znovu zkontroluje podmínku job_name IS NULL. Je to nepravda a B se neaktualizuje - B nevybere další řádek, ale pouze znovu zkontroluje a vrátí prázdný výsledek.
@joegester:SELECT FOR UPDATE není problém, protože všechny tabulky jsou uzamčeny.
Možná existuje jiný způsob, jak to udělat - pokud místo toho smažete a vložíte řádky (do jiné tabulky?) a nastavíte NULL. Ale nejsem si jistý jak.