La déconnection de SQL Server provoque des problèmes de pool de connection

J'ai un service Windows qui reçoit des messages via RabbitMQ, cela triggers un gestionnaire d'events qui fait un peu de travail, puis tente de persister le résultat dans la database. Il est enfilé en utilisant:

ThreadPool.QueueUserWorkItem(ProcessMessageOnThread, messageReceived); 

ProcessMessageOnThread est une méthode qui effectue le travail sur le messageReceived qui est une représentation du message extrait de RabbitMQ.

Dans des circonstances normales, le service Windows fonctionnait comme prévu, c'est-à-dire dequeue, process et persistent.

Je veux m'assurer que tous mes messages sont traités et traités correctement, donc si je ne peux pas ouvrir une connection à SQL Server, je remets simplement le message pour qu'il soit traité à nouveau (j'espère que SQL Server être de return, sinon cela continue – et je vais bien avec ça).

Maintenant, le problème survient lorsque le process a été exécuté comme prévu pendant un certain time, le pool de connections SQL Server a été rempli et SQL Server est déconnecté, maintenant c'est quand les choses deviennent un peu instables.

Une des deux choses peut arriver:

  • Une exception est levée sur connection.Open() – cependant j'attrape ceci et je ne m'inquiète pas pour ça

  • Une exception est lancée sur cmd.ExecuteNonQuery() – où cmd.ExecuteNonQuery() une procédure stockée

C'est la deuxième option que j'ai besoin de comprendre comment gérer. Auparavant, je supposais que toute exception ici signifiait qu'il y avait un problème avec datatables que je transmettais dans la procédure stockée et que je devais donc simplement les déplacer hors de la queue et que quelque chose d'autre l'parsing.

Cependant , maintenant je pense que j'ai besoin d'une nouvelle approche pour gérer les cas où l'exception est à faire avec la connection n'étant pas réellement établie.

J'ai jeté un coup d'oeil à la class SqlException et remarqué une propriété appelée Class qui a cette description Gets the severity level of the error returned from SQL Server , maintenant l'information sur ceci dit:

Les messages d'un niveau de gravité de 10 ou less sont informatifs et indiquent les problèmes causés par des erreurs dans les informations qu'un user a saisies. Les niveaux de gravité de 11 à 16 sont générés par l'user et peuvent être corrigés par l'user. Les niveaux de gravité de 17 à 25 indiquent des erreurs logicielles ou matérielles. Lorsqu'une erreur de niveau 17, 18 ou 19 se produit, vous pouvez continuer à travailler, même si vous ne pouvez pas exécuter une instruction particulière.

Cela signifie-t-il que je dois vérifier if (ex.Class > 16) alors le message de remise en queue parce que le problème est lié à la connection, else il est plus probable que des données malformées soient envoyées à la procédure stockée ?

Donc, la question est, comment dois-je faire la gestion des exceptions et comment puis-je détecter lors de l'appel de cmd.ExecuteNonQuery() si l'exception levée est due à une connection déconnectée.


Mettre à jour:

J'ai déjà rencontré des problèmes avec des connections qui n'étaient pas renvoyées au pool (cela était dû à des problèmes de threads) et j'ai corrigé ces problèmes, donc je suis confiant que le problème ne concerne pas les connections qui ne returnnent pas dans le pool. De plus, la logique autour de l'utilisation des connections est si simple que je m'assure qu'elles sont fermées de manière cohérente … donc je suis plus intéressé par les réponses à faire avec la déconnection du server Sql puis la capture du comportement de cmd.ExecuteNonQuery ()

Les connections dans le pool de connection peuvent entrer dans un état étrange pour diverses raisons, qui ont toutes à voir avec une mauvaise design de l'application:

  • Fermeture de la connection avant son lecteur de données associé
  • Modifier un paramètre (tel que le niveau d'isolation de la transaction) que le pool ne réinitialise pas
  • Démarrage d'une requête asynchronous ( BeginOpenReader ), puis renvoi de la connection au pool avant le triggersment du gestionnaire asynchronous

Vous devez examiner votre application et vous assurer que les connections sont correctement renvoyées au pool. Une chose qui peut aider le debugging est la réduction de la taille du pool d'applications dans un paramètre de développement. Vous modifiez la taille du pool dans la string de connection:

 ...;Integrated Security=SSPI;Max Pool Size=2;Pooling=True; 

Cela rend les problèmes de pool très faciles à reproduire.

Si vous ne trouvez pas la cause, mais que vous devez tout de même déployer un correctif, vous pouvez utiliser ClearPool ou ClearAllPools . Un bon endroit à faire est lorsque vous détectez l'une des exceptions suspectes après Open() ou ExecuteNonQuery() . Les deux sont des methods statiques sur la class SqlConnection :

 SqlConnection.ClearPool(yourConnection); 

Ou pour une approche encore plus grossière:

 SqlConnection.ClearAllPools() 

Notez qu'il s'agit essentiellement de la gestion des exceptions Pokémon . Si cela fonctionne, vous n'aurez aucune idée pourquoi. 🙂