Tengo una solución práctica para ti, una que he visto implementada en un proyecto en mi lugar de trabajo. En lugar de usar solo 0 y 1 para incompleto y completo, amplíe su conjunto para incluir más casos.
Llamemos a esa columna estado . Aquí están los diferentes valores de esa columna y los estados correspondientes del trabajo.
- Cuando el estado es 0, ningún subproceso de trabajo ha seleccionado el trabajo.
- Cuando el estado es 1, el trabajo ha sido seleccionado por un subproceso de trabajo y está en proceso.
- Cuando el estado es 2, el trabajo ha fallado. (Debe considerar la posibilidad de falla en el procesamiento).
- Cuando el estado es 3, el trabajo se ha completado.
Sus subprocesos deben contener una lógica tal que solo seleccione trabajos cuyo estado sea 0 y cambie el estado a 1. Esto impedirá que otros subprocesos seleccionen aquellos trabajos que están en proceso. Cuando se completa el trabajo, el estado se establece en 3 y si el trabajo falla, el estado se establece en 2. Luego, el subproceso puede continuar y buscar otro trabajo que aún debe completarse.
También puede pedir a los subprocesos que consideren seleccionar trabajos de estado 2, pero tendrá que definir la lógica para especificar un número finito de reintentos.
EDITAR:
Después de una larga discusión , nos topamos con la solución juntos. Mi respuesta anterior es buena en un estado más generalizado cuando el 'trabajo' es un proceso que lleva algún tiempo completar. Pero ese no fue el caso en el problema del OP.
Entonces, la solución que finalmente funcionó fue 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;