Sua solução com o sinalizador parece viável e acho que a única coisa necessária é fazer o bloqueio expirar. Basicamente, a maneira como eu arquitetaria o bloqueio seria escrever um carimbo de data e hora quando o bloqueio foi feito e fazer com que o processo tivesse que atualizar o bloqueio de vez em quando (ou seja, a cada 30 segundos) enquanto ainda está trabalhando no registro. Se o processo morrer ou falhar em concluir o trabalho, o bloqueio expirará e outros processos poderão desbloquear se mais do que o dobro do período de tempo limite decorrido.
Quando um processo termina de trabalhar em um registro, ele limpa o sinalizador de bloqueio e marca o registro como processado (novamente outro sinalizador).
Você provavelmente desejará ter dois campos:um que armazenaria o sinalizador de bloqueio de carimbo de data e hora e outro que indicaria qual processo possui o bloqueio (caso você se importe com isso). Estou assumindo que existe algum tipo de chave que pode ser usada para ordenar os registros na tabela de forma que o conceito de "próxima ação" seja significativo.
Você pode usar uma consulta como esta para obter o próximo registro a ser processado:
-- find the next available process and "lock" it by updating it's flag
UPDATE actions_tabe
SET LockFlag = @timestamp,
Process = @processname
WHERE Id IN (SELECT Id
FROM actions_table
WHERE LockFlag IS null
AND IsComplete = '0'
AND ScheduledTime < now()
ORDER BY Scheduledtime ASC, Id ASC
LIMIT 1);
-- return the Id and Action of the record that was just marked above
SELECT Id, Action
FROM actions_table
WHERE Process = @processname
Exemplo de violino aqui:http://sqlfiddle.com/#!11/9c120/26 /1