Quel est l'effet d'avoir une transaction ouverte dans MSSQL depuis trop longtemps?

11

Je me demande simplement ce qui se passe si vous commencez une transaction dans une base de données et oubliez de la valider ou de l'annuler. Le serveur sera-t-il en panne? Disons que vous l'avez laissé pendant 3 jours.

Il y a aussi des utilisateurs qui l'utilisent en supposant que les autres utilisateurs ne savaient pas qu'il existe une transaction non fermée (supposons simplement que les utilisateurs insèrent simplement des données dans la base de données). Quelles sont les conséquences de cette action?

JanLeeYu
la source

Réponses:

14

Avoir une transaction ouverte en soi n'aura presque aucune conséquence. Un simple

BEGIN TRANSACTION
-- wait for a while, doing nothing
-- wait a bit longer
COMMIT

contiendra, au pire, quelques octets de valeurs d'état. Pas grave.

La plupart des programmes feront un travail réel au sein de la transaction et c'est une autre question. Le but d'une transaction est que vous puissiez être sûr que plusieurs faits dans la base de données sont vrais simultanément, même si d'autres utilisateurs écrivent simultanément dans la même base de données.

Prenons l'exemple canonique du transfert d'argent entre comptes bancaires. Le système doit garantir que le compte source existe, qu'il dispose de fonds suffisants, que le compte de destination existe et que le débit et le crédit se produisent ou ne se produisent ni l'un ni l'autre. Il doit garantir cela pendant que d'autres transactions se produisent, peut-être même entre ces deux comptes. Le système y parvient en prenant des verrous sur les tables concernées. Les verrous pris et la quantité de travail des autres que vous voyez sont contrôlés par le niveau d'isolement des transactions .

Donc, si vous faites beaucoup de travail, il y a de fortes chances que d'autres transactions soient mises en file d'attente en attendant les objets sur lesquels vous détenez des verrous. Cela réduira le débit global du système. Finalement, ils atteindront les limites de délai d'expiration et échoueront, ce qui est un problème pour le comportement global du système. Si vous utilisez un niveau d'isolement optimiste, votre transaction peut échouer lorsque vous essayez une validation en raison du travail des autres.

Le maintien des verrous nécessite des ressources système. Il s'agit de mémoire que le système ne peut pas utiliser pour traiter d'autres demandes, ce qui réduit le débit.

Si beaucoup de travail a été effectué, le système peut choisir d'effectuer une escalade des verrous . Au lieu de verrouiller des lignes individuelles, la table entière sera verrouillée. Ensuite, davantage d'utilisateurs simultanés seront affectés, le débit du système diminuera davantage et l'impact de l'application sera plus important.

Les modifications de données sont écrites dans le fichier journal, tout comme les verrous qui les protègent. Ceux-ci ne peuvent pas être effacés du journal tant que la transaction n'est pas validée. Par conséquent, une transaction très longue peut provoquer un ballonnement du fichier journal avec les problèmes associés.

Si le travail en cours utilise tempdb, ce qui est probable pour les charges de travail importantes, les ressources peuvent être bloquées jusqu'à la fin de la transaction. Dans des cas extrêmes, cela peut entraîner l'échec d'autres tâches car il n'y a plus assez de place pour elles. J'ai eu des cas où une mise à jour mal codée remplissait tempdb, il n'y avait donc pas suffisamment de disque pour le tri d'un rapport et le rapport a échoué.

Si vous choisissez d'annuler la transaction ou si le système échoue et se rétablit, le temps nécessaire pour que le système redevienne disponible dépendra de la quantité de travail effectuée. Le simple fait d'ouvrir une transaction n'affectera pas le temps de récupération, c'est la quantité de travail qui a été effectuée. Si la transaction était ouverte mais inactive pendant une heure, la récupération sera presque instantanée. S'il écrivait constamment pendant cette heure, la règle générale est que le temps de récupération sera également d'environ une heure.

Comme vous pouvez le voir, une longue transaction peut être problématique. Pour les systèmes OLTP, la meilleure pratique consiste à avoir une transaction de base de données par transaction commerciale. Pour le processus de travail par lots, entrez des blocs, avec des validations fréquentes et une logique de redémarrage codée. En règle générale, plusieurs milliers d'enregistrements peuvent être traités dans une seule transaction de base de données, mais cela doit être testé pour la concurrence et la consommation de ressources.

Ne soyez pas tenté d'aller à l'autre extrême et d'éviter complètement les transactions et les verrous. Si vous devez maintenir la cohérence de vos données (et pourquoi utiliseriez-vous une base de données?), Les niveaux d'isolement et les transactions ont un objectif très important. Découvrez vos options et décidez de l'équilibre entre concurrence et exactitude avec lequel vous êtes prêt à vivre pour chaque partie de votre application.

Michael Green
la source
même s'il est ouvert pendant trois jours?
JanLeeYu
Oui, même pendant trois jours. Le point important est la quantité de travail qui a été effectuée pendant que le TX est ouvert, pas seulement depuis combien de temps il est ouvert. Bien sûr, en tant qu'administrateur de base de données, vous voudrez peut-être demander au propriétaire de la transaction pourquoi il a besoin qu'elle soit ouverte si longtemps. Lorsque j'ai dirigé une équipe DBA, j'ai enregistré tous les TX ouverts depuis plus de 30 minutes et j'ai eu une conversation avec le propriétaire.
Michael Green
D'ACCORD. Merci pour l'excellente explication. Bien que tout le monde ait aussi bien fait.
JanLeeYu
Quel soulagement ... Merci encore pour la réponse.
JanLeeYu
"MISE À JOUR mal codée" Yup. Vu ca. Une instruction de mise à jour à l'intérieur d'une boucle qui n'a pas qualifié certains noms et a donné lieu à un comportement similaire à 1 = 1, donc elle a mis à jour la table entière pour chaque itération de la boucle (ce qui a également mis les mauvaises données sur la plupart de ces lignes).
jpmc26
6

Votre plus grande conséquence sera le blocage des objets utilisés dans la transaction. Surtout si vous supposez que vos utilisateurs insèrent des données, cette transaction de longue durée peut inclure des instructions SELECT sur les tables couramment utilisées. Les déclarations de mise à jour de vos utilisateurs peuvent ne pas être en mesure d'obtenir le verrou nécessaire pour terminer leurs mises à jour ou insertions.

Une activité secondaire qui pourrait se produire est l'activité du fichier journal, par exemple, si vous mettez à jour un grand ensemble de données, la partie du journal que la transaction utilise est maintenue active pendant la durée de cette transaction. Vous ne pourrez pas réutiliser cette partie du journal tant que la transaction n'est pas validée ou annulée. Dans les scénarios où vous pourriez être dans un système OLTP très actif, cela pourrait entraîner une croissance rapide de votre fichier journal, remplissant votre périphérique de stockage.

Andriy M
la source
par exemple, celui qui a créé la transaction est déconnecté du serveur, pourra-t-il se reconnecter au serveur pour fermer la transaction?
JanLeeYu
Cela dépendra, si la transaction était dans un environnement qui utilisait MSDTC, cela pourrait être une transaction orpheline. Dans ce cas, aucun utilisateur ne pourrait plus le fermer lui-même ... le DBA devrait intervenir pour le gérer. En dehors de cela, vous devriez généralement voir la transaction être annulée par SQL Server lorsqu'il se déconnecte ... mais encore une fois sur les transactions importantes qui peuvent ne pas être le cas à chaque fois.
Dans le cas où cela se produirait, l'administrateur pourra-t-il toujours clôturer la transaction correctement?
JanLeeYu
Je ne peux pas répondre à cela, tout dépend. J'ai eu des cas où le serveur a dû être redémarré, ou l'instance a basculé sur le nœud / réplique secondaire.
4

Une transaction incomplète peut contenir un grand nombre de verrous et provoquer un blocage

Lorsqu'une transaction n'est pas terminée soit parce qu'une requête arrive à expiration soit parce que le lot est annulé au milieu d'une transaction sans émettre une instruction COMMIT ou ROLLBACK pour terminer la transaction, la transaction est laissée ouverte et tous les verrous acquis au cours de cette transaction continuent qui se tiendra. Les transactions ultérieures exécutées sous la même connexion sont traitées comme des transactions imbriquées, de sorte que tous les verrous acquis dans ces transactions terminées ne sont pas libérés. Ce problème se répète avec toutes les transactions exécutées à partir de la même connexion jusqu'à ce qu'un ROLLBACK soit exécuté. Par conséquent, un grand nombre de verrous sont maintenus, les utilisateurs sont bloqués et les transactions sont perdues, ce qui entraîne des données différentes de celles que vous attendez.

la source

Pimp Juice IT
la source
par exemple, celui qui a créé la transaction est déconnecté du serveur, pourra-t-il se reconnecter au serveur pour fermer la transaction?
JanLeeYu
Une fois que SQL Server sait que la connexion a été perdue, il annule la transaction. Voir ici dba.stackexchange.com/questions/47404/… . Si le même utilisateur se reconnecte, ce sera une session différente et ne peut donc pas "adopter" en quelque sorte l'ancienne transaction.
Michael Green