PostgreSQL
 sql >> Base de Dados >  >> RDS >> PostgreSQL

Consistência no postgresql com bloqueio e seleção para atualização

BEGIN; 
LOCK TABLE slots IN ACCESS EXCLUSIVE MODE; 
UPDATE slots SET job_name = '111' WHERE id IN (SELECT id FROM slots WHERE job_name IS NULL LIMIT 1) RETURNING *;
COMMIT;

Isso parece funcionar em Read Committed. É apenas sql (igual ao seu código) e pode ser executado em uma chamada (mais rápido).

@Seth Robertson:Não é seguro sem LOCK TABLE e sem loop while.

Se houver transação A e transação B ao mesmo tempo:A selecionará a primeira linha e B selecionará a primeira linha. A bloqueará e atualizará a linha, B terá que esperar até que A confirme. Então B irá verificar novamente a condição job_name IS NULL. É falso e B não atualizará - B não selecionará a próxima linha, mas apenas verificará novamente e retornará um resultado vazio.

@joegester:SELECT FOR UPDATE não é o problema porque todas as tabelas estão bloqueadas.

Talvez haja outra maneira de fazer o trabalho - se você excluir e inserir linhas (em outra tabela?) em vez de definir NULL. Mas não tenho certeza de como.