2017-06-20 2 views
0

J'ai une situation où je dois:Comment puis-je verrouiller une ligne et utiliser le verrou sur plusieurs transactions?

  1. Lire la valeur d'une ligne.
  2. Si la valeur d'une colonne est 'X', effectuez l'action A. Sinon, effectuez l'action B.
  3. Si nous avons effectué l'action A, mettez à jour la colonne avec le résultat de l'action.

L'action A n'est pas une opération de base de données, elle peut prendre un certain temps et n'est pas réversible. L'action B n'est pas une opération de base de données, mais elle est très rapide à exécuter. La séquence est exécutée sur plusieurs threads, sur plusieurs serveurs.

Actuellement, nous n'avons pas de verrouillage, et donc occasionnellement nous voyons l'action A être exécutée plusieurs fois, alors que cela ne devrait se produire qu'une seule fois. Je pense que ma seule solution ici est d'en quelque sorte envelopper la séquence ci-dessus avec un étape de verrouillage de verrouillage et un étape de verrouillage de la libération, et je ne sais pas comment faire cela.

J'ai vu a similar question, où la réponse était d'ajouter des colonnes 'locked' et 'acquiry time' à la ligne. Cependant, dans cette situation, le PO ne se souciait pas de ré-acquérir fréquemment l'écluse. Si je devais tourner-attendre que le verrou précédent expire chaque fois que je voulais exécuter la séquence, la performance de mon serveur serait probablement sortie par la fenêtre.

Y at-il quelque chose de construit dans SQL que je puisse utiliser ici?

Répondre

5

Mettez à jour la valeur "X" en "en attente".

À la fin de l'action A, mettez à jour "pending" à quoi que ce soit.

Aucun verrouillage requis.

+0

Oh wow, classique X Y problème. Je n'ai même pas pensé à ça. –

+0

Est-ce que cela ne va pas encore avoir une chance que deux thread interrogent la ligne en même temps, et donc les deux threads voient la ligne comme 'X', et les deux tentent de la mettre à jour en attente? –

+0

@AndrewWilliamson: Si vous avez fait un select au niveau intermédiaire et puis une mise à jour. Mais si vous faites juste une mise à jour, cela devrait être atomique (sauf si vous jouez à des jeux SET ISOLATION_LEVEL). – tpdi