Incremento simultâneo do contador do PostgreSQL

9

Preciso manter uma tabela estatística para um projeto, composta por uma lista de itens e seu uso (pense em algo como um site no qual você gostaria de contar exibições de página). Cada vez que um item é instanciado, preciso aumentar o uso do item específico.

Minha primeira implementação é:

statistics(
  id      integer NOT NULL,
  name    character varying(255) NOT NULL,
  usage   integer NOT NULL DEFAULT 0,
);


UPDATE statistics 
  SET usage = usage + 1
WHERE name = '<name>';

Minhas preocupações são sobre desempenho e concorrência. O processo de atualização será instanciado por várias dezenas (talvez 80-120) de dispositivos e poderá ocorrer várias vezes por segundo; portanto, minhas perguntas são:

1) esse método preservará a simultaneidade? (ou seja, se mais de um dispositivo solicitar a atualização "ao mesmo tempo", todas as solicitações serão contadas?)

2) você pode sugerir a melhor maneira de alcançar o resultado? Espero ter carga ao escrever as atualizações, enquanto as leituras me seriam muito mais frequentes. Existe uma função específica para incrementar valores? Estou olhando para "sequência", mas não tenho certeza se esse é o caminho certo ...

Muito obrigado antecipadamente por qualquer conselho

estudante
fonte

Respostas:

5

A segunda atualização aguardaria a confirmação da atualização anterior nas mesmas linhas, mas verá o valor confirmado.

Suponha duas transações simultâneas atualizando a mesma linha com um valor inicial de 0

Tempo Transação 1 Valor T1 Transação 2 Valor T2
-------------------------------------------------- ------------
1 atualização ... 1 0
2 1 atualização .. "indefinido"
                                (espera) 
3 confirmar 1 2
4 1 confirmação 2
5 2 2 

"Valor T1" e "Valor T2" significa o valor que essa transação vê.

Se quiser ter certeza de capturar situações em que há alterações "incompatíveis" (por exemplo, uma transação configurando a usagecoluna para um valor específico, em vez de apenas incrementá-lo), você poderá colocar todas as transações no nível de isolamento "serializável". Mas você precisará se preparar para o tratamento de erros.

Atualizações para nomes diferentes podem ser executadas simultaneamente sem esperas (porque linhas diferentes são afetadas).

SELECTs nunca será bloqueado, mas verá apenas valores confirmados.

um cavalo sem nome
fonte