Aide pour résoudre SqlException: le délai a expiré lors de la connexion, en l'absence de charge

j'ai un serveur hébergeant un site web qui a presque zéro trafic.

Quelques personnes (<20) entrent dans le site tous les jours, et quelques lecteurs RSS sont abonnés à certains flux que nous diffusons.

presque tous les soirs, un lecteur RSS nous frappe au milieu de la nuit et obtient une exception que le site ne peut pas se connecter au serveur SQL en raison d'un délai dans la connexion. Les détails sont très bizarres, donc je cherche de l'aide sur quel pourrait être le problème, puisque je ne sais plus où commencer à chercher.

nous utilisons ASP.Net MVC, Entity Framework, et SQL Server 2008 over Windows Server 2008. La machine est une boîte dédiée que nous avons obtenu d'un fournisseur pas exactement de premier niveau, de sorte que les choses pourraient être configurées de manière non optimale, ou qui sait quoi d'autre.

La boîte est aussi assez petite, et n'a que 1 Go de RAM, mais elle devrait prendre le genre de charge que nous avons pour le moment...

Je copie la pile d'appels complète ci-dessous, mais d'abord, certaines des choses que nous savons:

  • l'erreur se produit toujours quand iTunes interroge notre site. Je pense que cela n'a rien à voir avec quoi que ce soit, mais la vérité est que nous ne l'obtenons que d'iTunes. Ma meilleure supposition est que cela se produit parce que seulement iTunes nous interroge à cette heure de la nuit où personne d'autre ne nous frappe.
  • une de nos théories est que le serveur SQL et IIS sont se battre pour la mémoire, et l'un d'eux se fait biper pour le disque hors de ne pas être utilisé, et quand quelqu'un "se réveille", il prend trop de temps pour tout lire à partir du disque dans la mémoire. Est-ce quelque chose qui pourrait potentiellement se produire? (Je m'en débarrasse en quelque sorte puisque cela ressemble à un problème de conception dans SQL Server si c'était possible)
  • j'ai également pensé à la possibilité que nous fuyons des connexions, car nous ne pouvons pas disposer des entités EF de manière appropriée ( voir ma question ici ). C'est la seule chose que j'ai pu trouver par Googler le problème. Je m'en débarrasse étant donné la charge extrêmement faible que nous avons.
  • cela arrive toujours pendant la nuit, donc c'est très probablement quelque chose lié au fait que rien ne s'est passé pendant un certain temps. Par exemple, je suis presque sûr que lorsque ces requêtes sont activées, le processus du serveur web a été recyclé et il démarre / re-JITting tout. Le re-JITting n'explique pas le SQL le délai d'attente, si.

mise à jour: nous avons attaché un profileur comme suggéré, et il a fallu un certain temps avant que nous ayons une nouvelle exception. C'est le nouveau truc que nous connaissons:

  • ayant le profileur attaché énormément réduit le nombre d'erreurs que nous avons. En fait, après en avoir normalement reçu plusieurs par jour, nous avons dû attendre 3 ou 4 jours pour que cela arrive une fois. Une fois que nous avons arrêté le profileur, il est retourné à la fréquence d'Erreur Normale (ou pire encore). Donc le profileur a quelque effet qui cache ce problème dans une certaine mesure, mais pas complètement.
  • en regardant la trace du profileur à côté du journal des requêtes IIS, il y a une correspondance attendue 1-1 entre les requêtes et les requêtes. Cependant, de temps en temps, je vois beaucoup de requêtes exécutées qui n'ont aucune corrélation avec le journal IIS. Effectivement, juste avant que le bug réel ait été enregistré, j'ai eu 750 requêtes sur une période de 3 minutes , qui étaient toutes complètement sans rapport avec les journaux de L'IIS. Le texte de la requête ressemble au genre de merde illisible que EF génère, et ils ne sont pas tous les mêmes, et ils ressemblent tous aux requêtes provenant du site web: même nom D'application, utilisateur, etc. Pour donner une idée à quel point c'est ridicule, le site a obtenu environ 370 demandes IIS qui ont frappé le DB, dans le cadre de 2 jours
  • ces requêtes inexpliquées ne provenaient pas du même processus client que les précédentes, bien qu'elles puissent encore provenir du site web, si le processus a été recyclé dans l'intervalle. Il y avait presque une heure d'absence d'activité entre la dernière requête expliquée et la première inexpliquée.
  • une de ces longues séries de requêtes que je ne sais pas d'où elles viennent est venue juste avant l'erreur que j'ai été enregistré, donc je crois que c'est l'idée que nous devrions suivre.
  • comme je m'y attendais à l'origine, lorsque la requête qui a lancé l'erreur a été exécutée, elle provenait d'un autre ClientProcessID que le précédent, (8 minutes plus tard que le précédent inexpliqué, et presque exactement une heure plus tard que le précédent IIS one). Cela signifie, pour moi, que le processus ouvrier avait effectivement été recyclé.
  • C'est quelque chose que je ne comprends absolument pas. Le journal de bord de L'IIS montre qu'une minute avant les requêtes d'erreur, 4 étaient parfaitement servies, bien que les requêtes pour ceux n'apparaissent pas du tout dans la trace. En fait, après ces 4 qui se sont bien passées, j'ai eu 4 exceptions jetées en succession rapide, ces 4 non plus n'apparaissent pas dans la trace (ce qui est logique puisque s'il y avait un délai dans la connexion la requête n'aurait jamais dû être exécutée, mais je ne vois pas les tentatives de connexions dans la trace non plus)

donc, en bref, je suis complètement aucune idée à ce sujet. Je ne trouve pas de raison pour ces centaines de requêtes qui se succèdent rapidement, mais je pense que cela doit avoir quelque chose à voir avec le problème.

Aussi, je ne sais pas comment diagnostiquer les problèmes de connexion...

Ou comment la trace du profileur peut passer à côté de certaines requêtes qui, selon IIS, sont passées par fine...

des idées?


il s'agit de l'exception information:

System.Data.SqlClient.SqlException: Timeout expired. The timeout period elapsed prior to completion of the operation or the server is not responding.

System.Data.EntityException: The underlying provider failed on Open. ---> System.Data.SqlClient.SqlException: Timeout expired.  The timeout period elapsed prior to completion of the operation or the server is not responding.
   at System.Data.ProviderBase.DbConnectionPool.GetConnection(DbConnection owningObject)
   at System.Data.ProviderBase.DbConnectionFactory.GetConnection(DbConnection owningConnection)
   at System.Data.ProviderBase.DbConnectionClosed.OpenConnection(DbConnection outerConnection, DbConnectionFactory connectionFactory)
   at System.Data.ProviderBase.DbConnectionClosed.OpenConnection(DbConnection outerConnection, DbConnectionFactory connectionFactory)
   at System.Data.SqlClient.SqlConnection.Open()
   at System.Data.EntityClient.EntityConnection.OpenStoreConnectionIf(Boolean openCondition, DbConnection storeConnectionToOpen, DbConnection originalConnection, String exceptionCode, String attemptedOperation, Boolean& closeStoreConnectionOnFailure)
   at System.Data.EntityClient.EntityConnection.OpenStoreConnectionIf(Boolean openCondition, DbConnection storeConnectionToOpen, DbConnection originalConnection, String exceptionCode, String attemptedOperation, Boolean& closeStoreConnectionOnFailure)
   --- End of inner exception stack trace ---
   at System.Data.EntityClient.EntityConnection.OpenStoreConnectionIf(Boolean openCondition, DbConnection storeConnectionToOpen, DbConnection originalConnection, String exceptionCode, String attemptedOperation, Boolean& closeStoreConnectionOnFailure)
   at System.Data.EntityClient.EntityConnection.Open()
   at System.Data.Objects.ObjectContext.EnsureConnection()
   at System.Data.Objects.ObjectQuery`1.GetResults(Nullable`1 forMergeOption)
   at System.Data.Objects.ObjectQuery`1.System.Collections.Generic.IEnumerable<T>.GetEnumerator()
   at System.Linq.Enumerable.FirstOrDefault[TSource](IEnumerable`1 source)
   at System.Data.Objects.ELinq.ObjectQueryProvider.<GetElementFunction>b__1[TResult](IEnumerable`1 sequence)
   at System.Data.Objects.ELinq.ObjectQueryProvider.ExecuteSingle[TResult](IEnumerable`1 query, Expression queryRoot)
   at System.Data.Objects.ELinq.ObjectQueryProvider.System.Linq.IQueryProvider.Execute[S](Expression expression)
   at System.Linq.Queryable.FirstOrDefault[TSource](IQueryable`1 source)
   at MyProject.Controllers.SitesController.Feed(Int32 id) in C:...Controller.cs:line 38
   at lambda_method(ExecutionScope , ControllerBase , Object[] )
   at System.Web.Mvc.ReflectedActionDescriptor.Execute(ControllerContext controllerContext, IDictionary`2 parameters)
   at System.Web.Mvc.ControllerActionInvoker.InvokeActionMethod(ControllerContext controllerContext, ActionDescriptor actionDescriptor, IDictionary`2 parameters)
   at System.Web.Mvc.ControllerActionInvoker.<>c__DisplayClassa.<InvokeActionMethodWithFilters>b__7()
   at System.Web.Mvc.ControllerActionInvoker.InvokeActionMethodFilter(IActionFilter filter, ActionExecutingContext preContext, Func`1 continuation)
   at System.Web.Mvc.ControllerActionInvoker.InvokeActionMethodWithFilters(ControllerContext controllerContext, IList`1 filters, ActionDescriptor actionDescriptor, IDictionary`2 parameters)
   at System.Web.Mvc.ControllerActionInvoker.InvokeAction(ControllerContext controllerContext, String actionName)
   at System.Web.Mvc.Controller.ExecuteCore()
   at System.Web.Mvc.MvcHandler.ProcessRequest(HttpContextBase httpContext)
   at System.Web.HttpApplication.CallHandlerExecutionStep.System.Web.HttpApplication.IExecutionStep.Execute()
   at System.Web.HttpApplication.ExecuteStep(IExecutionStep step, Boolean& completedSynchronously)

toutes les idées seront énormément appréciées.

29
demandé sur Community 2009-09-14 18:39:03

3 réponses

Pas Assez De Mémoire

il s'agit très probablement d'un problème de mémoire, peut-être aggravé ou déclenché par d'autres choses, mais qui demeure intrinsèquement un problème de mémoire. il y a deux autres possibilités (moins probables), que vous devriez vérifier et éliminer d'abord (parce qu'il est facile de le faire):

Possibilités Faciles À Vérifier:

  1. vous pouvez avoir "Auto Close" activé: Auto Close peut avoir exactement ce comportement, cependant il est rare qu'il soit allumé. Pour vérifier cela, dans SSMS faites un clic droit sur votre base de données d'application, sélectionnez "Propriétés", puis sélectionnez le volet "Options". Regardez L'Entrée" Auto Close " et assurez-vous qu'elle est définie à False. Vérifiez aussi tempdb.

  2. Travaux de l'Agent SQL peuvent être à l'origine: Vérifier l'Agent du Journal de l'Historique pour voir si il y avait des travaux toujours en cours d'exécution pendant les événements. N'oubliez pas de vérifier l'entretien les emplois aussi, comme des choses comme la reconstruction des indices sont souvent cités comme des problèmes de performance pendant qu'ils sont en cours d'exécution. Ce sont des candidats invraisemblables maintenant, seulement parce qu'ils ne seraient normalement pas affectés par le profileur.

pourquoi ça ressemble à un problème de mémoire:

si ceux-ci ne montrent rien, alors vous devriez vérifier les problèmes de mémoire. Je soupçonne la mémoire comme la cause dans votre cas parce que:

  • vous avez 1 Go de mémoire: bien que ce soit techniquement au-dessus du Minimum pour SQL Server, il est bien en dessous de ce qui est recommandé pour SQL Server, et bien en dessous de ce qui, d'après mon expérience, est acceptable pour la production, même pour un serveur légèrement chargé.

  • vous exécutez IIS et SQL Server sur la même boîte: ce N'est pas recommandé par lui-même, en grande partie en raison de la prétention pour la mémoire qui en résulte, mais avec seulement 1 Go de mémoire il en résulte IIS, l'application, le serveur SQL, L'OS et toutes les autres tâches et/ou la maintenance se battent tous pour très peu de mémoire. La façon dont Windows gère ceci est de donner de la mémoire aux processus actifs en l'éloignant agressivement des processus non actifs. Il peut prendre plusieurs secondes, voire quelques minutes pour un grand processus comme SQL Server pour récupérer assez de mémoire pour pouvoir répondre à une demande dans cette situation.

  • Profiler fait 90% de la problème go away: C'est un gros indice que la mémoire est probablement le problème, parce que typiquement, les choses comme Profiler ont exactement cet effet sur ce problème particulier: la tâche Profiler garde le serveur SQL juste un petit bit actif tout le temps. Souvent, c'est juste assez d'activité pour le garder hors de la liste des "charognards" de L'OS, ou au moins réduit quelque peu son impact.

Comment vérifier la mémoire comme le Coupable:

  1. éteignez le profileur: il a un effet Heisenberg sur le problème, donc vous devez l'éteindre ou vous ne serez pas en mesure de voir le problème de façon fiable.

  2. lancer un système de surveillance (perfmon.exe) à partir d'une autre boîte, qui se connecte à distance au service de collecte perfomrance sur la boîte sur laquelle votre serveur SQL et IIS tournent. vous pouvez très facilement le faire en enlevant d'abord les trois les statistiques par défaut (elles sont locales seulement), et ensuite ajouter les statistiques nécessaires (ci-dessous), mais assurez-vous de changer le nom de L'ordinateur dans le premier drop-down pour se connecter à votre boîte SQL.

  3. envoyer les données collectées dans un fichier en créant un" contre-journal " sur perfmon. Si vous n'êtes pas familier avec cela, alors la chose la plus facile à faire est probablement de recueillir les données à un onglet ou fichier séparé par virgule que vous pouvez ouvrir avec Excel pour analyser.

  4. configurez votre perfmon pour collecter dans un fichier et ajoutez les compteurs suivants:

    -- Processeur\ % Temps Processeur [Total]

    -- PhysicalDisk\% temps inactif [ pour chaque disque ]

    -- Disque Physique\Avg. Longueur de la file d'attente du disque [ pour chaque disque ]

    -- Memory\Pages / sec

    -- Mémoire\Page Lit/sec

    -- Mémoire\Mégaoctets Disponibles

    -- Interface réseau \ Octets Total / sec [ pour chaque interface utilisée ]

    -- \% Temps Processeur[ voir ci-dessous ]

    -- \Défauts de Page/s[ voir ci-dessous ]

    -- ensemble de travail [ voir ci-dessous ]

  5. pour la Les compteurs de processus (ci-dessus) vous voulez inclure le sqlserver.processus exe, tout processus IIS et tout processus d'application stable. Notez que cela ne fonctionnera que pour les processus" stables". Les processus qui sont continuellement recréés au besoin, ne peuvent pas être saisis de cette façon parce qu'il n'y a aucun moyen de Les spécifier avant qu'ils n'existent.

  6. exécutez cette collection dans un fichier pendant la période où le problème se produit le plus fréquemment. Définir la collection intervalle de quelque chose de proche de 10-15 secondes. (cette recueille beaucoup de données, mais vous aurez besoin de cette résolution à choisir les événements distincts).

  7. après un ou plusieurs incidents, arrêtez la collecte et ouvrez votre fichier de données collecté avec Excel. Vous aurez probablement à reformater la colonne timestamp pour être utilement visible et montrer heures minutes et secondes. Utilisez votre journal de bord de L'IIS pour trouver l'heure exacte des incidents, puis regardez perfmon de données pour voir ce qui se passait avant et après l'incident. En particulier, vous voulez voir si son jeu de travail était petite et grande après, avec beaucoup de page défaillant entre les deux. C'est le signe le plus évident de ce problème.

SOLUTIONS:

séparez IIS et SQL Server sur deux boîtes différentes (de préférence) ou ajoutez plus de mémoire à la boîte. Je pense que 3-4 GO devrait être un minimum.

et ce truc bizarre D'EF?

le problème ici est qu'il est très probablement périphérique ou seulement contributif à votre problème principal. Rappelez-vous que Profiler fait 90% de vos incidents disparaître, de sorte que ce qui reste, mai être un problème différent, ou il peut être seulement le plus extrême aggravant du problème. En raison de son comportement, je suppose qu'il est soit en train de recycler sa cache ou là est une autre maintenance de base des processus du serveur d'application.

48
répondu RBarryYoung 2009-09-29 16:21:28

Je comparerais l'heure d'arrêt avec l'heure d'exécution de votre sauvegarde nocturne. Si elles coïncident, vous pouvez configurer votre flux RSS pour être statique pour l'époque.

une autre chose à essayer (même si ce n'est pas exactement une réponse) est d'exécuter immédiatement sp_who quand vous obtenez une exception de timeout. Il ne sera pas tout (le processus offensant pourrait être fait au moment où vous exécutez ce), mais vous pouvez obtenir de la chance.

vous pouvez également allumer SQL Profiler lorsque vous rentrez chez vous pour la nuit et passer à travers l'activité le lendemain matin si vous voyez l'erreur à nouveau. Assurez-vous simplement de ne pas l'exécuter à partir du serveur lui-même (je suis presque sûr qu'il vous le rappelle quand il démarre).

EDIT: s'attaquer à la mise à jour.

est-ce que EF met à jour/crée son cache? Il pourrait expliquer l'abondance de requêtes à un moment donné et pourquoi aucune requête n'a de base de données hits plus tard.

sinon, vous avez un heisenbug. La seule chose que je peux penser que vous pouvez ajouter est beaucoup plus de journalisation (dans un fichier ou le journal d'événements).

1
répondu Austin Salonen 2009-09-29 15:13:48

ça sent un truc croné qui court en même temps. Comme le dit RBarryYoung.. des renforts nocturnes ou ça pourrait être autre chose. Avez-vous un accès root au serveur? Tu vois les crontabs?

est-ce que ce pourrait être un plugin d'indexation plein texte au-dessus du serveur SQL qui exécute ses procédures de réindexage près du moment où vous rencontrez les problèmes?

0
répondu 2009-09-29 15:21:03