Dans un tableau où chaque ligne a un compteur (juste une valeur entière), j'ai besoin d'obtenir la valeur actuelle et de l'augmenter en même temps .
Effectivement, je veux faire ceci:
SELECT counter FROM table WHERE id=123
UPDATE table SET counter=counter+1 WHERE id=123
Mais faire cela comme deux requêtes n'est évidemment pas thread-safe: plusieurs processus faisant la même chose (sur la même ligne) peuvent obtenir la même valeur de compteur. Je leur ai besoin de tout être unique, de sorte que chaque processus obtiendrait la réelle valeur actuelle et l' augmenter par un.
Je peux penser à une construction où j'implémente un verrou manuel par ligne, mais je me demande s'il y a un moyen plus simple de le faire?
Réponses:
Les déclarations de mise à jour fonctionnent parfaitement bien sans le sélectionner avant! Étant donné que les instructions simples sont sûres par définition, même deux requêtes UPDATE effectuées en même temps uniquement entraîneront une incrémentation de la ligne deux fois.
Si vous voulez réellement sélectionner la valeur de votre script PHP, faire quelque chose avec lui et que vous souhaitez mettre à jour cette valeur de compteur exacte, vous pouvez faire ce qui suit:
Cela démarre une nouvelle transaction, puis sélectionne les lignes que vous souhaitez mettre à jour et les verrouille exclusivement. Vous pouvez ensuite mettre à jour ceux-ci en toute sécurité sans vous soucier des autres clients qui modifient leur contenu ou même qui accèdent aux lignes verrouillées. Enfin, vous devez valider vos modifications.
Vous devriez également lire quelque chose sur les niveaux d'isolement . Vous ne voulez probablement pas une valeur comme
READ UNCOMMITTED
niveau d'isolement. Tout le reste devrait convenir à ce cas d'utilisation.la source
UPDATE table SET counter = counter + 1
est suffisamment atomique? Avez-vous toujours besoin des relevés de transaction qui l'entourent?FOR UPDATE
et de transactions, la valeur que vous avez sélectionnée peut être différente de celle qui a été utilisée dans la requête de mise à jour. Ma combinaison de requêtes verrouille la ligne dès que la valeur est sélectionnée et garantit donc que cette valeur de compteur exacte sera utilisée dans la requête de mise à jour.