Eu tenho users
mesa
CREATE TABLE tasks(
id UUID PRIMARY KEY,
status TEXT REFERENCES statuses, -- available statuses are 'NEW', 'PENDING', 'PROCESSING', 'COMPLETE'
created_at TIMESTAMP WITH TIME ZONE NOT NULL DEFAULT NULL
);
Quero ter certeza de que apenas um processo mudará o status de PENDING
para PROCESSING
no caso de várias tentativas de atualizações simultâneas; o restante deve observar zero linhas atualizadas.
A alteração do status da tarefa é acionada pelo processamento de solicitações HTTP externas. É importante que apenas uma solicitação resulte em sucesso. O restante deve detectar a alteração e retornar 409. Conflito. Não temos controle sobre quantas solicitações simultâneas podemos receber.
A instrução de atualização é a primeira coisa feita como parte de uma transação maior, depois que update
o processo observa que ele atualizou tasks
a linha (a contagem de linhas atualizadas é 1), ele posteriormente insere/atualiza alguns dados em outras tabelas, etc.
Eu testei a seguinte consulta de atualização
UPDATE tasks
SET status = 'PROCESSING'
WHERE id = '00000000-0000-0000-0000-000000000000' AND status = 'PENDING'
usando Java JDBC, múltiplos threads, conexões etc. e observo que apenas um processo faz atualizações ao usar o nível de isolamento padrão READ COMMITTED
.
Quando pensei sobre esse problema, pensei que precisaria FOR UPDATE
de um nível UPDATE
de declaração ou SERIALIZABLE
isolamento na transação, mas em testes reais não consegui detectar inconsistências no caso de múltiplas atualizações.
Minha pergunta: é suficiente filtrar id
e status
garantir que apenas um processo realizará a atualização ou preciso de ações adicionais para excluir comportamentos inesperados em geral?