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;
Wydaje się, że to działa w Read Committed. Jest to tylko sql (tak samo jak twój kod) i może być wykonany w jednym wywołaniu (szybciej).
@Seth Robertson:Bez LOCK TABLE i pętli while nie jest to bezpieczne.
Jeśli istnieje transakcja A i transakcja B w tym samym czasie:A wybierze pierwszy wiersz, a B wybierze pierwszy wiersz. A zablokuje i zaktualizuje wiersz, B musi poczekać na zatwierdzenie A. Następnie B ponownie sprawdzi warunek nazwa_zadania IS NULL. To jest fałszywe i B nie zaktualizuje się - B nie wybierze następnego wiersza, ale tylko ponownie sprawdzi i zwróci pusty wynik.
@joegester:WYBIERZ DO AKTUALIZACJI nie stanowi problemu, ponieważ wszystkie tabele są zablokowane.
Może istnieje inny sposób wykonania zadania - jeśli usuniesz i wstawisz wiersze (w innej tabeli?) zamiast tego ustawisz NULL. Ale nie jestem pewien jak.