Ho una soluzione pratica per te, che ho visto implementata in un progetto sul mio posto di lavoro. Invece di utilizzare solo 0 e 1 per incompleto e completato, espandi il tuo set per includere più casi.
Chiamiamo quella colonna stato . Ecco i diversi valori di quella colonna e gli stati corrispondenti del lavoro.
- Quando lo stato è 0, il lavoro non è stato prelevato da nessun thread di lavoro.
- Quando lo stato è 1, il lavoro è stato prelevato da un thread di lavoro ed è in elaborazione.
- Quando lo stato è 2, il lavoro non è riuscito. (Dovresti considerare la possibilità di un errore nell'elaborazione.)
- Quando lo stato è 3, il lavoro è stato completato.
I tuoi thread dovrebbero contenere una logica tale che raccolga solo i lavori per i quali lo stato è 0 e cambi lo stato in 1. Ciò non consentirà ad altri thread di raccogliere quei lavori che sono in elaborazione. Al termine del lavoro, lo stato è impostato su 3 e se il lavoro non riesce, lo stato è impostato su 2. Quindi il thread può andare avanti e cercare un altro lavoro che deve ancora essere completato.
Potresti anche chiedere ai thread di prendere in considerazione l'assunzione di lavori di stato 2, ma dovrai definire la logica per specificare un numero finito di tentativi.
MODIFICA:
Dopo una lunga discussione , siamo incappati insieme nella soluzione. La mia risposta sopra è buona in uno stato più generalizzato quando il "lavoro" è un processo che richiede del tempo per essere completato. Ma non era così nel problema dell'OP.
Quindi la soluzione che alla fine ha funzionato è stata questa:
BEGIN
SELECT * FROM Jobs WHERE JobID = (SELECT * FROM Jobs WHERE completed = 0 LIMIT 1) LOCK IN SHARE MODE;
UPDATE Jobs SET completed = 1 WHERE JobID = (PREVIOUS ID);
COMMIT;