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;
Dit lijkt te werken in Read Committed. Het is alleen sql (hetzelfde als uw code) en kan in één aanroep (sneller) worden uitgevoerd.
@Seth Robertson:Het is niet veilig zonder LOCK TABLE en zonder while-lus.
Als er tegelijkertijd transactie A en transactie B zijn:A selecteert de eerste rij en B selecteert de eerste rij. A zal de rij vergrendelen en bijwerken, B moet wachten tot A zich commit. Dan zal B de voorwaarde job_name IS NULL opnieuw controleren. Het is niet waar en B wordt niet bijgewerkt - B zal de volgende rij niet selecteren, maar zal alleen opnieuw controleren en een leeg resultaat retourneren.
@joegester:SELECT FOR UPDATE is niet het probleem, want alle tafels zijn vergrendeld.
Misschien is er een andere manier om het werk te doen - als u rijen verwijdert en invoegt (in een andere tabel?) in plaats van NULL in te stellen. Maar ik weet niet zeker hoe.