Incrément de compteur simultané PostgreSQL

9

J'ai besoin de maintenir un tableau statistique pour un projet, composé d'une liste d'éléments et de leur utilisation (pensez à quelque chose comme un site Web dans lequel vous souhaitez compter les pages vues). Chaque fois qu'un élément est instancié, j'ai besoin d'augmenter l'utilisation de l'élément spécifique.

Ma première implémentation est:

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>';

Mes préoccupations concernent les performances et la concurrence. Le processus de mise à jour sera instancié par plusieurs dizaines (peut-être 80-120) et pourrait se produire plusieurs fois par seconde, donc mes questions sont les suivantes:

1) Cette méthode préservera-t-elle la concurrence? (c.-à-d. si plusieurs appareils demandent la mise à jour "en même temps", chaque demande sera-t-elle prise en compte?)

2) pouvez-vous suggérer une meilleure façon d'obtenir le résultat? Je m'attends à avoir la charge d'écrire les mises à jour, tandis que les lectures me seraient beaucoup plus fréquentes. Existe-t-il une fonction spécifique pour incrémenter les valeurs? Je regarde la "séquence" mais je ne sais pas si c'est la bonne façon ...

Merci beaucoup d'avance pour tout conseil

étudiant
la source

Réponses:

5

La deuxième mise à jour attendra que la mise à jour précédente sur les mêmes lignes soit validée, mais verra alors la valeur validée.

Supposons que deux transactions simultanées mettent à jour la même ligne avec une valeur initiale de 0

Transaction temporelle 1 Valeur T1 Transaction 2 Valeur T2
-------------------------------------------------- ------------
1 mise à jour ... 1 0
2 1 mise à jour .. "non défini"
                                (attend) 
3 commit 1 2
4 1 commit 2
5 2 2 

"Valeur T1" et "Valeur T2" signifie la valeur que cette transaction voit.

Si vous voulez vous assurer de détecter les situations où il y a des changements "incompatibles" (par exemple, une transaction définissant la usagecolonne sur une valeur spécifique, plutôt que de simplement l'incrémenter), vous pouvez placer toutes les transactions dans le niveau d'isolement "sérialisable". Mais vous devrez alors vous préparer à la gestion des erreurs.

Les mises à jour de différents noms peuvent s'exécuter simultanément sans attente (car différentes lignes sont affectées).

SELECTs ne sera jamais bloqué mais ne verra que les valeurs validées.

un cheval sans nom
la source