Mysql
 sql >> Base de données >  >> RDS >> Mysql

Insérer une ligne et éviter les conditions de concurrence (PHP/MySQL)

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.