2010-01-27 11 views
2

Je suis très confus.Anomalie de mise à jour perdue dans la commande de mise à jour du serveur SQL Server

J'ai une transaction au niveau d'isolation ReadCommitted. Entre autres choses, je suis aussi mise à jour d'une contre-valeur en elle, quelque chose de similaire à ci-dessous:

Update tblCount set counter = counter + 1 

Mon application est une application de bureau et cette transaction arrive à se produire assez fréquemment et en même temps. Nous avons récemment remarqué une erreur que parfois la valeur du compteur n'est pas mise à jour ou est manquée. Nous insérons également un enregistrement sur chaque mise à jour du compteur, nous sommes donc sûrs que les enregistrements ont été insérés mais que le compteur ne parvient pas à se mettre à jour. Cela arrive une fois en 2000 transactions simultanées. Je doute sérieusement qu'il s'agisse d'une anomalie de mise à jour perdue, mais si vous regardez la commande ci-dessus, il suffit de mettre à jour le compteur de sa propre valeur: si j'ai commencé une transaction et que la transaction a atteint cette déclaration, aurait dû verrouiller la ligne. Cela ne devrait pas causer de mise à jour perdue, mais cela arrive d'une manière ou d'une autre.

Est-ce que cette commande de mise à jour fonctionne en deux parties? Comme d'abord, il lit la valeur du compteur (au cours de laquelle il n'obtient pas le verrou exclusif), puis écrit la nouvelle valeur calculée (lorsqu'il reçoit un verrou exclusif)?

S'il vous plaît aider, j'ai vraiment confus.

+3

Exécutez-vous ceci dans une transaction elle-même? Il ne va pas verrouiller quoi que ce soit s'il n'est pas dans une transaction malgré les données que vous attendez qu'il lise. –

+0

Aucune clause WHERE? 2000 transactions essayant toutes de mettre à jour la même ligne, cela ne va pas à l'échelle. –

+0

Oui cela est dans la transaction .NET avec le niveau d'isolement ReadCommitted, et oui il a une clause where dans la requête comme ci-dessous, Mise à jour tblCount set counter = compteur + 1 où counterID = 10 – Javed

Répondre

1

Etes-vous sûr que le SQL réussit toujours? Qu'est-ce que je veux dire, pourrait-il être quelque chose comme un temps de verrouillage occasionnel? Traitez-vous les exceptions SQL dans votre code .Net d'une manière qui les connaîtra (par exemple, un message contextuel ou une entrée de journal)?

2

La commande de mise à jour ne fonctionne pas en deux parties. Cela ne marche que dans un seul.

Il se passe quelque chose d'autre, et ma première hypothèse serait que votre transaction est en train de reculer pour une autre raison. Sur ces 2 000 transactions, par exemple, il se peut que l'on recule - surtout si vous faites une tonne de choses en même temps - et cela n'a pas du tout réussi. Cette mise à jour n'a peut-être pas causé le problème: vous avez peut-être des blocages en raison d'autres transactions et ils échouent avant la commande de mise à jour (ou pendant la commande de mise à jour).

Je ferais un zoom arrière et poser des questions sur la gestion des erreurs de la transaction. Faites-vous tout dans les blocs try/catch? Capturez-vous les niveaux d'erreur lorsque les transactions échouent? Sinon, vous devrez capturer une trace avec Profiler pour savoir ce qui se passe.

Questions connexes