web-dev-qa-db-fra.com

Délai d'expiration de transaction SQL Server

Existe-t-il un moyen dans SQL Server 2008 R2 de provoquer un délai d'expiration pour une modification de base de données impliquant une transaction? Nous avons un scénario où notre code d'application se bloque ou lève une exception et ne parvient pas à effectuer une restauration ou une validation. Cela provoque alors le blocage d'autres sessions en attendant la fin de la transaction.

9
David Gray Wright

Étendre la réponse de Mark ...

Lorsqu'un événement de délai d'expiration du client se produit (.net CommandTimeout par exemple), le client envoie un "ABORT" à SQL Server. SQL Server abandonne alors simplement le traitement des requêtes. Aucune transaction n'est annulée, aucun verrou n'est libéré.

Maintenant, la connexion est renvoyée au pool de connexions, elle n'est donc pas fermée sur SQL Server. Si cela se produit (via KILL ou redémarrage du client, etc.), les transactions + les verrous seront effacés. Notez que sp_reset_connection ne les effacera pas ou ne les effacera pas, même s'il est annoncé pour le faire

Ces détritus de l'avortement bloqueront d'autres processus.

La façon de rendre les transactions + verrous SQL Server claires sur le délai d'expiration du client (strictement, les événements ABORT) consiste à utiliser SET XACT_ABORT ON.

Vous pouvez vérifier que cela ouvre 2 fenêtres de requête dans SSMS:

Fenêtre 1:

Dans le menu Query..Query Options définissez un délai d'expiration de 5 secondes, puis exécutez cette

BEGIN TRAN
UPDATE sometable WITH (TABLOCKX) SET foo = foo WHERE 1 = 0;
WAITFOR DELAY '00:00:10' -- just has to be longer then timeout

Fenêtre 2, cela attendra pour toujours (ou atteindra votre délai d'attente)

SELECT * FROM sometable

SET XACT_ABORT ON a aussi des effets secondaires intéressants:

  • @@ TRANCOUNT est défini sur zéro lors de la restauration implicite mais l'erreur 266 est supprimée (cela se produit si @@ TRANCOUNT est différent à l'entrée et à la sortie d'un proc stocké)
  • XACT_STATE sera -1 (c'est "condamné")

La combinaison de cela signifie que vous ne pouvez pas utiliser SAVEPOINTS (bien que je ne me souvienne pas du comportement exact) pour les validations/annulations partielles. Qui me convient

Liens SO sur SET XACT_ABORT:

Sur les proc stockés imbriqués:

Sur sp_reset_connection:

20
gbn

Je réponds à cette question avec hésitation car il n'y a pas suffisamment d'informations dans votre description du problème pour être sûr à 100% que c'est le meilleur conseil. "Le blocage ou lève une exception" suggère que la source du problème n'est pas bien comprise, alors soyez prudent.

La solution la plus simple est probablement SET XACT_ABORT ON.

XACT_ABORT détermine si SQL Server annulera une transaction en cas d'erreur d'exécution. Le défaut SET XACT_ABORT OFF annulera uniquement l'instruction qui a provoqué une erreur, laissant toute transaction parent ouverte.

L'effet secondaire "gotcha" du paramètre par défaut est qu'un délai d'attente peut provoquer exactement le même problème, une transaction ouverte qui est la responsabilité des clients à gérer et à annuler. Si le client n'essaye pas/catch/rollback, la transaction restera ouverte jusqu'à ce qu'elle soit traitée avec (et je cite @gbn) l'ultra-violence de KILL <spid>.

Les articles souvent cités Erland Sommarskog sur gestion des erreurs dans SQL Server contiennent tous les antécédents et la stratégie dont vous avez besoin pour faire face à ces scénarios et plus encore.

Modifier (commentaire suivant): Pour identifier les transactions ouvertes, sp_whoisactive est probablement la fonctionnalité la plus complète.

11
Mark Storey-Smith