Tenho uma solução prática para você, que vi implementada em um projeto no meu local de trabalho. Em vez de usar apenas 0 e 1 para incompletos e concluídos, expanda seu conjunto para incluir mais casos.
Vamos chamar essa coluna de status . Aqui estão os diferentes valores dessa coluna e os estados correspondentes do trabalho.
- Quando o status é 0, o trabalho não foi selecionado por nenhum thread de trabalho.
- Quando o status é 1, o trabalho foi selecionado por um thread de trabalho e está em processo.
- Quando o status é 2, o trabalho falhou. (Você deve considerar a possibilidade de falha no processamento.)
- Quando o status é 3, o trabalho foi concluído.
Seus encadeamentos devem conter uma lógica de modo que apenas pegue os trabalhos para quem o status é 0 e altere o status para 1. Isso não permitirá que outros encadeamentos peguem os trabalhos que estão em processo. Quando o trabalho é concluído, o status é definido como 3 e, se o trabalho falhar, o status é definido como 2. Em seguida, o encadeamento pode seguir em frente e procurar outro trabalho que ainda não foi concluído.
Você também pode pedir aos encadeamentos que considerem pegar trabalhos de status 2, mas você terá que definir a lógica para especificar um número finito de tentativas.
EDITAR:
Após uma longa discussão , encontramos a solução juntos. Minha resposta acima é boa em um estado mais generalizado quando o 'trabalho' é um processo que leva algum tempo para ser concluído. Mas esse não foi o caso do problema do OP.
Então, a solução que acabou funcionando foi esta:
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;