Quero um determinado comportamento para transações no Postgresql, mas não sei dizer se é possível. Eu descreveria esse comportamento como “Bloqueio de leitura otimista”, mas esse não parece ser o termo certo para isso.
Aqui está o comportamento que eu quero:
- Minha transação começa. Seu nível de isolamento de transação é “leitura repetível” ou “serializável”.
- Na transação eu li a linha A.
- Na transação, leio e escrevo mais um pouco, mas nunca atualizo a linha A.
- Tento confirmar a transação.
Agora preciso que a transação falhe, se a linha A tiver sido alterada por alguma outra transação durante o tempo de vida da minha transação. Se a linha A não foi alterada, desejo que a transação seja confirmada.
Existe uma maneira de fazer isso no Postgresql?
Minha abordagem alternativa seria atualizar a linha A com algum valor aleatório na minha transação, para forçar um conflito de gravação. No entanto, isso significaria muitos conflitos desnecessários, porque sem forçar conflitos, a linha A raramente seria atualizada, mas frequentemente lida.
Você provavelmente está falando sobre uma situação como esta:
Agora a transação 1 resume os eventos:
Antes que a transação 1 possa ser confirmada, a transação 2 insere uma linha mais antiga:
E não haverá erro quando a transação 1 for confirmada.
Uma solução possível é que a transação 2 leia a tabela de resumo após inserir a nova linha. Vejamos como isso funciona:
Transação 1:
Transação 2:
Agora, quando a transação 1 for confirmada:
Como a transação 2 olhou
summary
e não viu a linha de resumo, ela foi executada logicamente antes da transação 1. Mas como a transação 1 não viu seus resultados, ela foi executada logicamente antes da transação 2. Essa contradição causa o erro de serialização.Se a transação 2 encontrar uma
summary
linha, ela estará em uma situação difícil e deverá reverter e descartar o novo valor ou tentar corrigir o resumo. Se isso não for uma opção, você terá que serializar verdadeiramente as operações com grandes bloqueios, o que não é muito atraente.