web-dev-qa-db-fra.com

ROLLBACK après COMMIT

J'ai plusieurs sessions de base de données dont l'une en bloque d'autres en raison d'une application gelée. Des transactions s'exécutent sur plusieurs sessions. J'ai besoin de tuer le bloqueur de tête en raison des délais d'expiration de la demande de verrouillage sur d'autres sessions. Après avoir tué cette session, un autre utilisateur a signalé une perte de données. Je suis presque sûr qu'ils ont engagé leurs transactions, mais ils semblent toujours avoir été annulés. Ils peuvent même le prouver car certains documents ont été imprimés et manquent de données par la suite.

Est-il possible que les transactions validées soient annulées en raison d'une annulation sur une autre session? Je ne pense pas, mais après avoir lu la documentation COMMIT j'ai des doutes. Ça dit:

Si @@ TRANCOUNT est supérieur à 1, COMMIT TRANSACTION ne diminue @@ TRANCOUNT que de 1 et la transaction reste active.

Lire la documentation TRANCOUNT il dit:

Renvoie le nombre d'instructions BEGIN TRANSACTION qui se sont produites sur la connexion actuelle.

La connexion actuelle est-elle donc la même chose qu'une session ou plusieurs sessions peuvent-elles partager la même connexion (peut-être en regroupant)? Et s'ils peuvent partager, comment cela se rapporte-t-il aux transactions? Se peut-il que ces transactions actives soient annulées ultérieurement et même après avoir été validées?

[edit] Pour être plus clair, certains utilisateurs n'ont pas obtenu de délai de verrouillage car leurs données n'étaient pas en conflit avec le bloqueur de tête. Ils ont commis des transactions, mais ces transactions semblaient avoir été annulées après avoir tué le bloqueur de têtes.

[Mise à jour 2018-03-29] Après un nouvel incident, j'ai eu l'occasion d'enquêter sur le problème pendant qu'il se produisait. Les journaux de transactions ont conclu que le problème était une transaction imbriquée qui n'a jamais été validée. L'application à l'origine du problème n'a pas été gelée, de sorte que l'utilisateur ne l'a jamais remarqué tant qu'il n'a pas fermé l'application. À ce stade, il a perdu ses données car la transaction a été annulée. J'ai accepté la meilleure réponse possible et c'est celle qui m'a dit qu'il n'était pas possible d'annuler une transaction engagée. Je suppose que ce n'est vraiment pas possible, c'est juste difficile de trouver le vrai problème.

4
Martin

Généralement, une transaction est exactement l'une des

  • engagé
  • annulées

Les transactions validées ne sont jamais annulées.
C'est ainsi que fonctionnent tous les SGBDR, sur principes ACID

Maintenant, il existe différents cas où il peut sembler que cette règle a été violée. Mais ce n'est pas le cas.

Avant d'examiner ces cas, différentes sessions utilisateur ne partagent pas de connexion. Chaque utilisateur/client dispose d'une connexion au SQL et tous sont isolés les uns des autres. Le regroupement de connexions n'affecte pas cela.

Points de sauvegarde

Vous pouvez ENREGISTRER une transaction et revenir à ce savepoin,

Autrement dit, vous pouvez partiellement valider/annuler si vous utilisez des points de sauvegarde, mais je n'ai jamais vu personne le faire dans le code de la vie réelle. Je ne m'étendrai pas plus.

Transactions imbriquées

Vous pouvez imbriquer des transactions, mais elles ne signifient vraiment rien
Autrement dit, SQL Server n'a pas vraiment de transitions imbriquées même si @@ TRANCOUNT peut être supérieur à un.

  • Un début incrémente @@ TRANCOUNT d'un
  • Une restauration mettra @@ TRANCOUNT à zéro
  • Un commit diminue @@ TRANCOUNT d'une unité

Une explication plus longue se trouve dans this SO answer

11
gbn

1) Sur le thème du retour en arrière des transactions engagées. La documentation que vous avez mentionnée "Si @@ TRANCOUNT est supérieur à 1" se produirait si, dans une seule session, vous imbriquiez des transactions. https://technet.Microsoft.com/en-us/library/ms189336%28v=sql.105%29.aspx?f=255&MSPPError=-2147217396

Dans ce cas, la transaction finale validerait ou annulerait son travail et toutes les transactions imbriquées.

2) Ce que vous avez décrit, c'est plusieurs sessions voulant démarrer plusieurs transactions mais bloquées. Vous observez une "perte de données" car un verrou compatible n'était pas disponible pour la transaction demandeuse et l'application n'a pas pu enregistrer ses données. J'ai utilisé le terme "perte de données" car c'est vraiment un problème d'application. L'application doit être codée pour réaliser qu'une transaction a échoué et essayer à nouveau ou avertir l'utilisateur final afin qu'il n'y ait pas de surprise.

Le moteur de la base de données a fait exactement ce pour quoi il avait été conçu et a empêché une violation du principe ACID.

1
Steve Hansen