Habituellement, la solution à ces problèmes de concurrence implique des transactions et un verrouillage optimiste :lorsque vous mettez à jour le compteur, ajoutez un where
clause pour vérifier l'ancienne valeur et compter le nombre de lignes mises à jour.
v = select value from counter where id=x.
update counter set value = v+1 where value = v and id=x
Si le compteur a été mis à jour entre-temps, la mise à jour ne modifiera aucune ligne. Vous savez donc que vous devez revenir en arrière et réessayer la transaction.
Un problème est que cela pourrait conduire à une forte conflit , avec seulement quelques transactions qui réussissent et beaucoup qui échouent.
Il peut alors être préférable de s'en tenir au verrouillage pessimiste , où vous verrouillez d'abord la ligne, puis la mettez à jour. Mais seul un benchmark vous le dira.
MODIFIER
Si vous utilisez une transaction sans verrouillage optimiste, le scénario suivant peut se produire.
Max authorized = 50. Current value = 49.
T1: start tx, read value --> 49
T2: start tx, read value --> 49
T1: update value --> 50, acquire a row lock
T1: commits --> release the lock
T2: update value --> 50, acquire a row lock
T2: commits --> release the lock
Les deux transactions réussissent, la valeur est 50, mais il y a une incohérence.