2008-08-19 32 views
32

Chaque maintenant et puis dans une application .NET volume élevé, vous pouvez voir cette exception lorsque vous essayez d'exécuter une requête:Comment gérez-vous les erreurs de niveau de transport dans SqlConnection?

System.Data.SqlClient.SqlException: A transport-level error has occurred when sending the request to the server.

D'après mes recherches, c'est quelque chose qui « arrive juste » et pas grand-chose peut être fait pour l'empêcher. Cela ne se produit pas à cause d'une mauvaise requête et ne peut généralement pas être dupliqué. Il se produit peut-être une fois tous les quelques jours dans un système OLTP occupé lorsque la connexion TCP à la base de données devient mauvaise pour une raison quelconque.

Je suis obligé de détecter cette erreur en analysant le message d'exception, puis en réessayant toute l'opération, en incluant l'utilisation d'une nouvelle connexion. Rien de tout cela est joli.

Quelqu'un at-il d'autres solutions?

+0

Augmenter la RAM –

+0

Avez-vous des statistiques sur la charge de votre serveur de base de données lorsque ces erreurs sont levées? Vous pouvez rencontrer des problèmes de base de données qui provoquent l'échec des connexions. –

+1

Cela * ne devrait pas arriver, même avec un volume transactionnel élevé. Nous exécutons en moyenne 25 000 transactions par seconde sur SQL Server 2005 Standard, et nous n'obtenons pas cette erreur. (À moins que le cluster ne tombe en panne, tous les 12 mois et plus, pas tous les quelques jours.) Sans plus d'informations, il semble qu'il y ait un problème de réseau entre votre serveur de base de données et vos serveurs d'applications. Pouvez-vous poster plus d'informations? – Portman

Répondre

0

J'utilise la couche de fiabilité autour de mes commandes de DB (abstraire loin dans le dépôt interfaece). Fondamentalement, c'est juste du code qui intercepte toute exception attendue (DbException et aussi InvalidOperationException, qui arrive à être levé sur les problèmes de connectivité), le connecte, capture des statistiques et réessaie tout à nouveau.

Avec cette couche de fiabilité présente, le service a été en mesure de survivre aux tests de résistance avec élégance (verrous morts constants, défaillances du réseau, etc.). La production est beaucoup moins hostile que cela.

PS: There is more on that here (avec un moyen simple de définir la fiabilité avec le DSL d'interception)

2

Pour répondre à votre question initiale:

Une façon plus élégante pour détecter cette erreur particulière, sans l'analyse du message d'erreur , est d'inspecter la propriété Number du SqlException.

(Cela renvoie effectivement le numéro d'erreur de la première SqlError dans la collection Errors, mais dans votre cas, l'erreur de transport devrait être le seul dans la collection.)

+0

+1 Non une réponse, mais c'est une idée utile. –

0

J'ai eu le même problème. J'ai demandé à mes amis geek réseau, et tous ont dit ce que les gens ont répondu ici: C'est la connexion entre l'ordinateur et le serveur de base de données. Dans mon cas, c'était mon fournisseur de services Internet, ou le routeur qui était le problème. Après une mise à jour du routeur, le problème s'est dissipé. Mais avez-vous d'autres abandons de connexion Internet de votre ordinateur ou serveur? J'ai eu ...

8

J'ai posté an answer on another question sur un autre sujet qui pourrait avoir une certaine utilité ici. Cette réponse impliquait des connexions SMB, pas SQL. Cependant, il était identique en ce qu'il impliquait une erreur de transport de bas niveau. Ce que nous avons trouvé était que dans une situation de charge lourde, il était assez facile pour le serveur distant de temporiser les connexions à la couche TCP simplement parce que le serveur était occupé. Une partie de la raison était les valeurs par défaut pour combien de fois TCP retransmettra les données sur Windows n'étaient pas appropriées pour notre situation.

Jetez un oeil à la registry settings for tuning TCP/IP sur Windows.En particulier, vous voulez regarder TcpMaxDataRetransmissions et peut-être TcpMaxConnectRetransmissions. Ceux-ci par défaut à 5 et 2 respectivement, essayez de les augmenter un peu sur le système client et dupliquer la situation de charge.

Ne soyez pas fous! TCP double le timeout à chaque retransmission successive, donc le comportement du timeout pour les mauvaises connexions peut devenir exponentiel sur vous si vous les augmentez trop. Comme je me souviens d'augmenter TcpMaxDataRetransmissions à 6 ou 7 résolu notre problème dans la grande majorité des cas.

1

J'ai vu cela se produire dans mon propre environnement un certain nombre de fois. L'application client dans ce cas est installée sur plusieurs machines. Certaines de ces machines sont des ordinateurs portables, les gens quittaient l'application en la déconnectant, puis en la rebranchant et en essayant de l'utiliser. Cela provoquera alors l'erreur que vous avez mentionnée. Mon premier point serait de regarder le réseau et de s'assurer que les serveurs ne sont pas sur DHCP et de renouveler les adresses IP à l'origine de cette erreur. Si ce n'est pas le cas, vous devez commencer à parcourir vos journaux d'événements à la recherche d'autres réseaux liés.

Malheureusement, il est comme indiqué ci-dessus une erreur de réseau. La principale chose que vous pouvez faire est de simplement surveiller les connexions en utilisant un outil comme netmon et de travailler à partir de là.

Bonne chance.

3

Cette blog post par Michael Aspengren explique le message d'erreur "Une erreur de niveau de transport s'est produite lors de l'envoi de la demande au serveur."

0

J'ai eu le même problème, mais c'était avec les demandes de service à une base de données SQL.

C'est ce que j'avais dans mon erreur de service journal:


System.Data.SqlClient.SqlException: Une erreur au niveau du transport a eu lieu lors de l'envoi de la requête au serveur. (Fournisseur: fournisseur TCP, erreur:. 0 - Une connexion existante a été fermée de force par l'hôte distant)


J'ai un C# suite de tests qui teste un service. Le service et la base de données étaient tous les deux sur des serveurs externes, donc j'ai pensé que cela pourrait être le problème. J'ai donc déployé le service et la base de données localement en vain. Le problème a continué. La suite de tests n'est même pas du tout un test de performance, donc je n'avais aucune idée de ce qui se passait. Le même test échouait à chaque fois, mais lorsque je désactivais ce test, un autre échouait continuellement.

J'ai essayé d'autres méthodes proposées sur Internet qui ne fonctionne pas non plus:

  • Augmentez les valeurs de registre des TcpMaxDataRetransmissions et TcpMaxConnectRetransmissions.
  • Désactivez l'option "Mémoire partagée" dans SQL Server Configuration Manager sous "Protocoles client" et triez TCP/IP au 1er dans la liste.
  • Cela peut se produire lorsque vous testez l'évolutivité avec un grand nombre de tentatives de connexion client. Pour résoudre ce problème, utilisez l'utilitaire regedit.exe pour ajouter une nouvelle valeur DWORD nommée SynAttackProtect à la clé de Registre HKEY_LOCAL_MACHINE \ SYSTEM \ CurrentControlSet \ Services \ Tcpip \ Parameters \ avec des données de valeur de 00000000.

Mon dernier recours était d'utiliser la vieillesse en disant "Essayez et essayez à nouveau". J'ai donc imbriqué des instructions try-catch pour m'assurer que si la connexion TCP/IP est perdue dans le protocole de communication inférieur, elle ne renonce pas là-bas mais essaie à nouveau. Cela fonctionne maintenant pour moi, mais ce n'est pas une solution très élégante.

+0

Merci pour vos commentaires. Si vous utilisez le pool de connexion, essayez appelez SqlConnection.Recycle() toutes les 10 minutes pour vous assurer que si SQLServer a tué une connexion, votre pool n'essaie toujours pas de l'utiliser. Si cela fonctionne, faites un rapport! – TheLegendaryCopyCoder

1

utilisation Enterprise Services avec des composants transactionnels

0

Pour autant que je peux dire, la classe 20 est le niveau de transport.

0

J'ai rencontré l'erreur de transport ce matin dans SSMS lors de la connexion à SQL 2008 R2 Express. J'essayais d'importer un CSV avec \ r \ n. J'ai codé ma terminaison de ligne pour 0x0d0x0a. Quand je l'ai changé à 0x0a, l'erreur s'est arrêtée. Je peux le changer d'avant en arrière et le regarder arriver/ne pas arriver.

BULK INSERT #t1 FROM 'C:\123\Import123.csv' WITH 
     (FIRSTROW = 1, FIELDTERMINATOR = ',', ROWTERMINATOR = '0x0d0x0a') 

Je pense que je ne suis pas en train d'écrire correctement mon terminaison de ligne parce que SQL parse un caractère à un moment alors que je suis en train de passer deux personnages.

De toute façon, cette erreur a 4 ans maintenant, mais elle peut fournir un peu d'information pour l'utilisateur suivant.

+0

Je pense que le problème ici était que le rowterminator est censé être une seule valeur binaire, qui pour le serveur SQL serait écrit comme 0x0d0a (pas de seconde 0x). – Zastai

+0

Salut! C'est lisse! Je vais essayer ça plus tard ce soir! –

0

Je voulais juste poster ici un correctif qui a fonctionné pour notre société sur les nouveaux logiciels que nous avons installés. Nous obtenions l'erreur suivante depuis le jour 1 sur le fichier journal du client: Le serveur n'a pas pu traiter la demande. ---> Une erreur de niveau de transport s'est produite lors de la réception des résultats du serveur. (provider: TCP Provider, error: 0 - La période d'expiration du sémaphore a expiré.) ---> La période d'expiration du sémaphore a expiré.

Ce qui a complètement résolu le problème était de configurer un agrégat de lien (LAG) sur notre commutateur. Notre serveur Dell FX1 a des lignes de fibre redondantes qui sortent de l'arrière. Nous n'avions pas réalisé que le commutateur dans lequel ils étaient branchés nécessitait la configuration d'un LAG sur ces deux ports. Voir détails ici: https://docs.meraki.com/display/MS/Switch+Ports#SwitchPorts-LinkAggregation