SPID endormi bloquant d'autres transactions


16

J'ai vraiment du mal à localiser certains blocages que nous rencontrons.

Le statut du SPID bloquant la racine est «sleep», le cmd est «AWAITING COMMAND» et le sqltextis SET TRANSACTION ISOLATION LEVEL READ COMMITTED.

Lorsque j'affiche le rapport Top Transactions by Blocked Transactions Count, l'instruction SQL de blocage est «-».

J'ai effectué une trace sur le SQL et lorsque le blocage se produit en traçant le SPID de blocage racine, mais cela ne m'a vraiment conduit nulle part. La dernière instruction trace est la même que sqltextci - dessus SET TRANSACTION ISOLATION LEVEL READ COMMITTED.

J'ai vérifié toutes les procédures stockées connexes que je peux trouver pour m'assurer qu'elles contiennent des instructions TRY / CATCH BEGIN TRAN / COMMIT TRAN / ROLLBACK TRAN (nous utilisons des procédures stockées pour tout, donc aucune instruction autonome n'est exécutée). Ce problème vient de se produire au cours des dernières 24 heures et personne ne prétend avoir apporté de modifications au système.

Solution: une de nos procédures stockées rarement utilisées avait une erreur avec un insert (le nombre de colonnes ne correspondait pas), mais nous sommes encore confus sur ce qui se passait exactement.

Lorsque vous examinez toutes les informations de trace, l'instruction EXEC pour cette procédure stockée a parfois été répertoriée, mais JAMAIS juste avant que le BLOC ne se produise sur le SPID bloquant. Il semblait que lors du démarrage du blocage, la trace n'enregistrait pas l'exécution (ni aucune des instructions qu'elle contenait). Cependant, il y a d'autres moments où la trace a enregistré son exécution et aucun blocage ne s'est produit.

Le rapport d'erreur de procédure stockée provenait d'un utilisateur, et j'ai pu trouver plusieurs instructions EXEC dans les traces et les exécuter dans SSMS. À aucun moment lorsque je les ai exécutés, nous avons eu un blocage ou ils se sont bloqués. Ils ont fonctionné comme prévu (le bloc catch s'est déclenché et a annulé la transaction après l'erreur). Après avoir résolu la correction de la procédure stockée, nous n'avons pas revu le problème.


Je suppose que le nom d'hôte du SPID bloquant n'a pas aidé du tout?
Jon Seigel

Non, c'est juste l'IP de l'un de nos serveurs Web ... Nous avons une autre idée de changer chaque connexion SQL pour chaque appel SPROC pendant le processus de connexion / d'enregistrement (qui, selon nous, est l'endroit où l'erreur se produit) en un nom d'utilisateur distinct qui peut aidez-nous à isoler quel SPROC pourrait être à l'origine du blocage.
Brad

1
TRY / CATCH n'attrapera pas les erreurs de compilation et une insertion de colonne non appariée serait une telle erreur de compilation. Cela ne déclencherait également jamais la plupart des événements XX: Completed profiler.
Remus Rusanu

1
Il ne s'agit en fait pas d'une erreur de compilation dans ce cas, car le développeur génial a utilisé INSERT INTO [table] SELECT * à partir de [othertable] et il n'a pas été détecté par un pair. J'ai exécuté le SPROC on Development 1000 fois à partir de ColdFusion en 3 sessions simultanées et il n'a jamais laissé ouverte une transaction comme c'était le cas en production.
Brad

Réponses:


10

D'après les commentaires, je suppose que vous avez eu un délai d'expiration de commande côté client qui a abandonné la requête SQL. Cela n'annule pas la transaction car la connexion reste ouverte sur SQL Server en raison du regroupement de connexions.

Donc, vous devez utiliser SET XACT_ABORT ON ou ajouter du code de restauration client

Voir SQL Server Transaction Timeout pour tous les détails sanglants


Tous nos SPROC contiennent des blocs TRY / CATCH et des instructions BEGIN TRAN / COMMIT TRAN / ROLLBACK TRAN, ROLLBACK étant dans le CATCH. XACT_ABORT aurait-il toujours un effet?
Brad

@Brad: oui. Voir mon lien. Le bloc catch n'est pas touché sur CommandTimeout
gbn

gbn: Merci. Je suis encore confus. Nos connexions sont définies pour ne jamais expirer (0). Donc, vous dites que si nous réutilisons les connexions, et qu'une connexion exécute un SPROC avec une erreur (qui a des blocs TRY / CATCH et TRAN), elle ne peut jamais exécuter le ROLLBACK dans le bloc CATCH, bloquant ainsi les tables et conservant une transaction ouvert? Cela n'a aucun sens pour moi.
Brad

@Brad: Un SPROC avec une erreur frappera le bloc CATCH. Je n'ai pas dit le contraire ou différent. Mais mon lien indique ce qui se passe si vous avez un CommandTimeout, qui est différent d'un ConnectionTimeout. Le client dit «abandonner» et SQL Server arrête le traitement. Ergo, le bloc CATCH ou rollback ou commit n'est jamais touché
gbn

Je ne pense pas que nous ayons spécifié un CommandTimeout. Toutes nos procédures stockées testent en utilisant sqlstress et doivent effectuer moins de 1000 ms à 10 utilisateurs 10 itérations (au minimum). Je suis toujours très confus sur ce qui s'est passé, mais je mets à jour la question avec ce que nous avons trouvé était le problème.
Brad

9

Utilisez le most_recent_sql_handle dans sys.dm_exec_connections pour voir la dernière instruction qui a été exécutée.

SELECT  t.text,
        QUOTENAME(OBJECT_SCHEMA_NAME(t.objectid, t.dbid)) + '.'
        + QUOTENAME(OBJECT_NAME(t.objectid, t.dbid)) proc_name,
        c.connect_time,
        s.last_request_start_time,
        s.last_request_end_time,
        s.status
FROM    sys.dm_exec_connections c
JOIN    sys.dm_exec_sessions s
        ON c.session_id = s.session_id
CROSS APPLY sys.dm_exec_sql_text(c.most_recent_sql_handle) t
WHERE   c.session_id = 72;--your blocking spid

Vérifiez également s'il y a des transactions ouvertes pour ce spid

SELECT  st.transaction_id,
        at.name,
        at.transaction_begin_time,
        at.transaction_state,
        at.transaction_status
FROM    sys.dm_tran_session_transactions st
JOIN    sys.dm_tran_active_transactions at
        ON st.transaction_id = at.transaction_id
WHERE   st.session_id = 72;--your blocking spid

Vous pouvez également utiliser DBCC INPUTBUFFER(spid)pour voir le dernier SQL exécuté.
Mike Fal

J'ai utilisé tous ceux-ci et la dernière commande est toujours celle que j'ai mise dans mon message d'origine: SET TRANSACTION ISOLATION LEVEL READ COMMITTED. J'ai également exécuté DBCC OPENTRAN et je peux voir qu'il y a une transaction ouverte pour le PID bloquant.
Brad

Ma première sélection vous donne également le nom de la procédure, si l'instruction fait effectivement partie d'une procédure.
Sebastian Meine

Je vous assure que nous n'utilisons aucune requête ad hoc de nos serveurs Web, et lorsque j'exécute cette première requête, même sans la clause WHERE, je n'obtiens le SPROC nommé que sur une poignée de sessions SQL, le reste de cette colonne est NULL.
Brad

Je remarque que j'ai des tonnes de sessions qui disent «SET TRANSACTION ISOLATION LEVEL READ COMMITTED» et toutes proviennent de ColdFusion (le principal script utilisé sur nos serveurs Web). Peut-être ColdFusion lorsque l'inactivité émet cette instruction pour maintenir ouverte une connexion (car elle est configurée pour maintenir les connexions ouvertes).
Brad

4

Avez-vous essayé d'utiliser sp_whoisactive d'Adam Machanic ? Il y a une option pour obtenir la commande externe pour voir si elle est vraiment dans un proc. Il se peut que l'application maintienne ouverte une transaction au lieu de la valider. Essayez également de regarder DBCC OPENTRAN .


Merci pour DBCC OPENTRAN. Cela me dit que le PID bloquant a une transaction ouverte, mais aucun autre détail n'est disponible. sp_whoisactive renvoie les mêmes informations sur le processus bloqué que j'ai pu obtenir par moi-même. Il n'y a toujours pas de détails sur ce qui se passe à part 'FIXER LE NIVEAU D'ISOLEMENT DE TRANSACTION LECTURE ENGAGÉE'
Brad
En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.