Le délai a expiré. Le délai d'expiration s'est écoulé avant la fin de l'opération ou le serveur ne répond pas. La déclaration est terminée

296

J'ai de nombreux utilisateurs sur mon site Web (20000-60000 par jour), qui est un site de téléchargement de fichiers mobiles. J'ai un accès à distance à mon serveur (serveur Windows 2008-R2).
J'ai déjà reçu des erreurs «Le serveur n'est pas disponible» , mais je vois maintenant une erreur de délai de connexion.
Je ne connais pas cela - pourquoi cela se produit-il et comment puis-je le corriger?

L'erreur complète est ci-dessous:

Erreur serveur dans l'application '/' Le délai a expiré. Le délai d'expiration s'est écoulé avant la fin de l'opération ou le serveur ne répond pas. La déclaration est terminée. Description: une exception non gérée s'est produite lors de l'exécution de la demande Web en cours. Veuillez consulter la trace de la pile pour plus d'informations sur l'erreur et son origine dans le code.

Détails de l'exception: System.Data.SqlClient.SqlException: le délai a expiré. Le délai d'expiration s'est écoulé avant la fin de l'opération ou le serveur ne répond pas. La déclaration est terminée.

Erreur source:

Une exception non gérée a été générée lors de l'exécution de la demande Web actuelle. Les informations concernant l'origine et l'emplacement de l'exception peuvent être identifiées à l'aide de la trace de pile d'exceptions ci-dessous.

Trace de la pile:

[SqlException (0x80131904): le délai a expiré. Le délai d'expiration s'est écoulé avant la fin de l'opération ou le serveur ne répond pas. L'instruction est terminée.]
System.Data.SqlClient.SqlConnection.OnError (exception SqlException, Boolean breakConnection) +404
System.Data.SqlClient.TdsParser.ThrowExceptionAndWarning () +412
System.Data.SqlClient.TdsParser.Run (RunBB , SqlCommand cmdHandler, SqlDataReader dataStream, BulkCopySimpleResultSet bulkCopyHandler, TdsParserStateObject stateObj) +1363
System.Data.SqlClient.SqlCommand.FinishExecuteReader (SqlDataReaderS3, String + RunBeServices, B6)
System.Data.SqlClient.SqlCommand.RunExecuteReaderTds (CommandBehavior cmdBehavior, RunBehavior runBehavior, Boolean returnStream, Boolean async) +6389442
System.Data.SqlClient.SqlCommand.RunExecuteReadeBordBehavior, RunBehavior, RunBe 538
System.Data.SqlClient.SqlCommand.InternalExecuteNonQuery (résultat DbAsyncResult, String methodName, Boolean sendToPipe) +689
System.Data.SqlClient.SqlCommand.ExecuteNonQuery () +327
Paramètres NovinMedia.Data.DbObject.RunProced [StringProcedName , Int32 et lignes affectées) +209
DataLayer.OnlineUsers.Update_SessionEnd_And_Online (Object Session_End, Boolean Online) +440
NiceFileExplorer.Global.Application_Start (expéditeur d'objet, EventArgs e) +163

[HttpException (0x80004005): le délai a expiré. Le délai d'expiration s'est écoulé avant la fin de l'opération ou le serveur ne répond pas. L'instruction a été terminée.]
System.Web.HttpApplicationFactory.EnsureAppStartCalledForIntegratedMode (contexte HttpContext, application HttpApplication) +4052053
System.Web.HttpApplication.RegisterEventSubscriptionsWithIIS (IntPtr appContext, HttpContext) ApplicationContextWordInfo
. InitSpecial (état HttpApplicationState, gestionnaires MethodInfo [], IntPtr appContext, contexte HttpContext) +352
System.Web.HttpApplicationFactory.GetSpecialApplicationInstance (IntPtr appContext, HttpContext context) +407
System.Web.Hosting.PipelineRapp + Application

[HttpException (0x80004005): le délai a expiré. Le délai d'expiration s'est écoulé avant la fin de l'opération ou le serveur ne répond pas. L'instruction a été arrêtée.]
System.Web.HttpRuntime.FirstRequestInit (contexte HttpContext) +11686928 System.Web.HttpRuntime.EnsureFirstRequestInit (contexte HttpContext) +141 System.Web.HttpRuntime.ProcessRequestNotificationWorkContext


EDIT APRÈS REPONSES:
mon Application_Starten Global.asaxest comme ci - dessous:

protected void Application_Start(object sender, EventArgs e)
{
    Application["OnlineUsers"] = 0;

    OnlineUsers.Update_SessionEnd_And_Online(
        DateTime.Now,
        false);

    AddTask("DoStuff", 10);
}

La procédure stockée appelée est:

ALTER Procedure [dbo].[sp_OnlineUsers_Update_SessionEnd_And_Online]
    @Session_End datetime,
    @Online bit
As
Begin
    Update OnlineUsers
    SET
        [Session_End] = @Session_End,
        [Online] = @Online

End

J'ai deux méthodes pour obtenir des utilisateurs en ligne:

  1. en utilisant Application["OnlineUsers"] = 0;
  2. l'autre utilisant la base de données

Donc, pour la méthode # 2, je réinitialise tous les OnlineUsers à Application_Start. Il y a plus de 482 751 enregistrements dans ce tableau.

SilverLight
la source
1
Comme il est dit ici, la valeur par défaut est de 15 secondes
V4Vendetta
1
Mieux vaut faire une analyse des causes profondes, Il existe diverses raisons pour provoquer un tel problème. Le plus élémentaire est la structure complexe de la requête. J'ai rencontré le même problème lorsque je récupère des images stockées en tant que valeurs hexadécimales dans le tableau.
Vijay Kumbhoje
Outre les causes ci-dessus, j'ajouterai une autre: Délai d'expiration du verrou: docs.microsoft.com/en-us/sql/t-sql/statements/… Si ce thread attend le verrouillage trop longtemps, il expirera en fonction de document ci-dessus.
Herbert Yu

Réponses:

345

Il semble que votre requête prenne plus de temps que prévu. À partir de votre trace de pile et de votre code, vous devriez pouvoir déterminer exactement de quelle requête il s'agit.

Ce type de délai d'attente peut avoir trois causes;

  1. Il y a une impasse quelque part
  2. Les statistiques de la base de données et / ou le cache du plan de requête sont incorrects
  3. La requête est trop complexe et doit être réglée

Un blocage peut être difficile à résoudre, mais il est facile de déterminer si tel est le cas. Connectez-vous à votre base de données avec Sql Server Management Studio. Dans le volet gauche, cliquez avec le bouton droit sur le nœud du serveur et sélectionnez Moniteur d'activité . Jetez un œil aux processus en cours. Normalement, la plupart seront inactifs ou en cours d'exécution. Lorsque le problème se produit, vous pouvez identifier tout processus bloqué par l'état du processus. Si vous cliquez avec le bouton droit sur le processus et sélectionnez les détails, il vous montrera la dernière requête exécutée par le processus.

Le deuxième problème obligera la base de données à utiliser un plan de requête sous-optimal. Il peut être résolu en effaçant les statistiques:

exec sp_updatestats

Si cela ne fonctionne pas, vous pouvez également essayer

dbcc freeproccache

Vous ne devriez pas le faire lorsque votre serveur est soumis à une charge importante, car il encourra temporairement un grand hit de performance car tous les proc et requêtes stockés sont recompilés lors de leur première exécution. Cependant, étant donné que vous déclarez que le problème se produit parfois et que la trace de pile indique que votre application démarre, je pense que vous exécutez une requête qui n'est exécutée qu'occasionnellement. Vous pouvez être mieux en forçant SQL Server à ne pas réutiliser un plan de requête précédent. Voir cette réponse pour plus de détails sur la façon de procéder.

J'ai déjà abordé le troisième problème, mais vous pouvez facilement déterminer si la requête doit être optimisée en exécutant la requête manuellement, par exemple en utilisant Sql Server Management Studio. Si la requête prend trop de temps, même après la réinitialisation des statistiques, vous devrez probablement la régler. Pour obtenir de l'aide, vous devez publier la requête exacte dans une nouvelle question.

Marnix van Valen
la source
39
J'avais cette même erreur mais dans une requête qui a "juste" pris 8 secondes ... et votre conseil sur la exec sp_updatestatsrésolution de mon problème. Merci beaucoup!
nrod
2
La résolution d'un problème comme celui-ci n'est presque jamais une question de réglage des délais d'expiration ou de la taille du pool de connexions. Vous devrez plonger et découvrir la cause première. Si vous avez besoin d'aide pour résoudre cette cause première, vous pouvez publier votre propre question.
Marnix van Valen
5
Ce n'est certainement pas une impasse. Cela peut être dû à un blocage excessif, mais les blocages sont résolus en une seconde et génèrent des erreurs différentes. Cela peut être un blocage excessif, mais pas un blocage.
Michael J Swart
1
sommes-nous sûrs qu'il s'agit d'un délai de commande et non d'un délai de connexion? "System.Data.SqlClient.SqlConnection.OnError" pour moi indique un problème de connexion.
Mike W
1
@PrashantPimpale Cela dépend Si vous avez un problème grave en production où des statistiques incorrectes entraînent de mauvais plans d'exécution, alors, cela pourrait être une solution. Sauf problèmes exceptionnels (comme une panne matérielle), la mise à jour des statistiques ne cassera pas votre base de données. Cela peut ralentir un peu les requêtes. En fin de compte, c'est votre appel.
Marnix van Valen
155

Dans votre code où vous exécutez la procédure stockée, vous devriez avoir quelque chose comme ceci:

SqlCommand c = new SqlCommand(...)
//...

Ajoutez une telle ligne de code:

c.CommandTimeout = 0;

Cela attendra autant de temps que nécessaire pour terminer l'opération.

Elastep
la source
144
Vous devez également savoir que la valeur 0 n'est pas recommandée : une valeur de 0 indique aucune limite et doit être évitée dans un CommandTimeout car une tentative d'exécution d'une commande attendra indéfiniment. Il est préférable d'apprendre le temps que prend la commande et d'augmenter la valeur du délai si nécessaire.
Otiel
7
Je suis d'accord avec Otiel et j'ai rejeté votre réponse: lorsque vous définissez la commande TimeTime sur 0, vous ne donnez pas au serveur Web une chance de récupérer à partir d'un serveur de base de données qui ne répond pas. Deuxièmement, lorsque vous atteignez le délai d'expiration par défaut, vous devez envisager de rechercher la cause. Dans la plupart des cas, il est préférable de corriger la requête que d'augmenter le délai d'expiration.
Maarten Kieft
10
Je ne tomberais pas dans le piège de ne pas le recommander. Cela a été très utile pour moi et mes tâches quotidiennes planifiées: avoir un délai infini n'empêche pas un processus de se terminer et de renvoyer une erreur en cas de problème. Autrement dit, cela vous permet simplement de permettre à une requête de se terminer quand elle en a besoin, sans vous poser de problèmes plus tard, car vous n'avez pas alloué suffisamment de temps pour que le processus se termine. Vous pouvez également éviter de verrouiller votre programme par le multithread.
WonderWorker
2
Oui, pour les transferts de données volumineux, ne pas définir cela n'a pas de sens. Si vous transférez des millions de lignes, ce que disent Otiel et BlackHawkDesign n'a pas de sens.
bluerubez
En 20 ans de développement centré sur les données, je n'ai jamais eu besoin de faire cela. Il existe presque toujours une solution raisonnablement simple qui offre de meilleures performances et ne crée pas la possibilité pour un seul processus de broyer une base de données toute la journée. La grande majorité des problèmes de performances de la base de données peuvent être réglés là où ils effectuent plusieurs ordres de grandeur plus rapidement. C'est-à-dire que ce processus que vous attendez 3 heures pour terminer, pourrait probablement être réglé sur 3 minutes ou même 3 secondes.
b_levitt
25

Vous pouvez définir la CommandTimeoutpropriété de la commande SQL pour autoriser la transaction SQL de longue durée.

Vous devrez peut-être également consulter la requête SQL à l'origine du délai d'expiration.

Kev Ritchie
la source
salut, "ou vous devez regarder la requête SQL qui provoque le délai d'attente" -> dans sql server 2008 où dois-je vérifier ce délai?
SilverLight
Vous devrez peut-être tester la procédure stockée appelée à partir de DataLayer.OnlineUsers.Update_SessionEnd_And_Online car la trace de pile semble pointer vers elle. Prenez une copie de la base de données en direct dans le test et exécutez la procédure stockée en transmettant les paramètres requis, si cela prend plus de 30 secondes, c'est pourquoi vous obtenez un délai d'expiration. Je suppose que vous avez accès à SQL Server Management Studio.
Kev Ritchie
oui, j'ai accès au serveur sql 2008. je devrais essayer votre chemin.
SilverLight
Si vous trouvez la procédure stockée à l'origine du problème, vous pouvez exécuter la requête contenue dans la procédure stockée via le conseiller de réglage de base de données qui vous suggérera si vous avez besoin d'index, etc. Lien ici msdn.microsoft.com/en-us/library /ms174202.aspx
Kev Ritchie
12

Bien que toutes les réponses antérieures traitent du problème, elles ne couvraient pas tous les cas.

Microsoft a reconnu le problème et l'a corrigé en 2011 pour les systèmes d'exploitation pris en charge, donc si vous obtenez la trace de la pile comme:

Timeout expired. The timeout period elapsed prior to completion of the operation or the server is not responding.
at System.Data.SqlClient.SqlInternalConnection.OnError(SqlException exception, Boolean breakConnection)
at System.Data.SqlClient.TdsParser.ThrowExceptionAndWarning()
at System.Data.SqlClient.TdsParserStateObject.ReadSniError(TdsParserStateObject stateObj, UInt32 error)
at System.Data.SqlClient.TdsParserStateObject.ReadSni(DbAsyncResult asyncResult, TdsParserStateObject stateObj)

vous devrez peut-être mettre à jour vos assemblys .NET.

Ce problème se produit en raison d'une erreur dans l'algorithme de nouvelle tentative de connexion pour les bases de données en miroir.

Lorsque l'algorithme de nouvelle tentative est utilisé, le fournisseur de données attend la fin du premier appel de lecture (SniReadSync). L'appel est envoyé à l'ordinateur principal qui exécute SQL Server et le temps d'attente est calculé en multipliant la valeur du délai d'expiration de la connexion par 0,08. Cependant, le fournisseur de données définit de manière incorrecte une connexion à un état condamné si une réponse est lente et si le premier appel SniReadSync n'est pas terminé avant l'expiration du délai d'attente.

Voir KB 2605597 pour plus de détails

https://support.microsoft.com/kb/2605597

matcheek
la source
9

Ce sera peut-être utile à quelqu'un. J'ai fait face au même problème et dans mon cas, la raison était que SqlConnection a été ouvert et non supprimé dans la méthode que j'ai appelée en boucle avec environ 2500 itérations. Le pool de connexions a été épuisé. Une élimination appropriée a résolu le problème.

éternité
la source
ce! exactement ça. Mon problème était que je tirais des méthodes sur un autre thread sans les attendre (car l'utilisateur n'a pas besoin d'un résultat de cette méthode, d'un script d'arrière-plan). Sans disposer (en utilisant des usingblocs), j'ai ce problème de délai d'attente. Cela semblait le résoudre.
CularBytes
avez-vous obtenu l'erreur de délai d'expiration avec le pool de connexions max atteint ou le délai d'expiration a expiré. Le délai d'expiration s'est écoulé avant la fin de l'opération ou le serveur ne répond pas. Par exemple, si vous recevez le pool maximal atteint, il est logique d'examiner la connexion qui a fui. mais, je reçois le serveur ne répond pas erreur.
Jeeva Subburaj
8

J'ai fait face au même problème que j'ai travaillé environ 3 jours. J'ai remarqué que notre nombre d'enregistrements n'est pas beaucoup, notre développeur principal conserve 2 images et empreintes digitales dans la base de données. Lorsque j'essaie de récupérer ces valeurs hexadécimales, cela prend beaucoup de temps, je calcule le temps moyen pour exécuter ma procédure, c'est environ 38 secondes. Le délai d'expiration de la commande par défaut est de 30 secondes, donc son temps inférieur à la moyenne requis pour exécuter ma procédure stockée. J'ai défini mon délai de commande comme ci-dessous

cmd.CommandTimeout = 50

et son bon fonctionnement mais parfois, si votre requête prend plus de 50 secondes, il provoquera la même erreur.

Vijay Kumbhoje
la source
8

Vous devez définir l'attribut CommandTimeout. Vous pouvez définir l'attribut CommandTimeout dans la classe enfant DbContext.

public partial class StudentDatabaseEntities : DbContext
{
    public StudentDatabaseEntities()
        : base("name=StudentDatabaseEntities")
    {
        this.Database.CommandTimeout = 180;
    }

    protected override void OnModelCreating(DbModelBuilder modelBuilder)
    {
        throw new UnintentionalCodeFirstException();
    }

    public virtual DbSet<StudentDbTable> StudentDbTables { get; set; }
}
Siddarth Kanted
la source
4

J'ai rencontré cette erreur récemment et après une brève enquête, j'ai constaté que nous manquions d'espace sur le disque contenant la base de données (moins de 1 Go).

Dès que j'ai déplacé les fichiers de base de données (.mdf et .ldf) vers un autre disque sur le même serveur (avec beaucoup plus d'espace), la même page (exécutant la requête) qui avait expiré s'est chargée en trois secondes.

Une autre chose à étudier, tout en essayant de résoudre cette erreur, est la taille des fichiers journaux de la base de données. Vos fichiers journaux devront peut-être être réduits.

Hafiz Adewuyi
la source
3

J'ai un problème avec les gros calculs dans sp_foo qui prennent beaucoup de temps, donc j'ai corrigé
avec ce petit code

public partial class FooEntities : DbContext
{
   public FooEntities()
         : base("name=FooEntities")
    {
        this.Configuration.LazyLoadingEnabled = false;

        // Get the ObjectContext related to this DbContext
        var objectContext = (this as IObjectContextAdapter).ObjectContext;

        // Sets the command timeout for all the commands
        objectContext.CommandTimeout = 380;
    }
Nabeel Iqbal
la source
3

Le délai d'expiration par défaut est de 15 secondes, pour changer cela, 0 est illimité, tout autre nombre est le nombre de secondes.

Dans du code

using (SqlCommand sqlCmd = new SqlCommand(sqlQueryString, sqlConnection))
   {
      sqlCmd.CommandTimeout = 0; // 0 = give it as much time as it needs to complete
      ...
    }

Dans votre Web.Config, "Délai d'expiration de la commande = 0;" ne pas expirer, ou comme ci-dessous 1 heure (3600 secondes)

  <add name="ConnectionString" connectionString="Data Source=ServerName;User ID=UserName;Password=Password;Command Timeout=3600;" providerName="System.Data.SqlClient" />
David C Fuchs
la source
2
Ce sont deux délais différents. Votre première suggestion répond à la question. Votre deuxième ne fonctionnerait que si le fournisseur de connexion le supportait, ce que SqlClient ne fait pas. En tout cas, un timeout de 0 n'est jamais une bonne idée en production. 30 secondes est la valeur par défaut habituelle.
Suncat2000
2

@SilverLight .. Il s'agit clairement d'un problème avec un objet Database. Il peut s'agir d'une requête mal écrite ou d'index manquants. Mais pour l'instant, je ne vous suggérerai pas d'augmenter le délai sans enquêter sur le problème avec vos objets de base de données

NovinMedia.Data.DbObject.RunProcedure(String storedProcName, IDataParameter[] parameters, Int32& rowsAffected) +209

Placez un point d'arrêt sur cette ligne de code pour connaître le nom de la procédure, puis optimisez la procédure en consultant son plan d'exécution.

Je ne peux pas vous aider davantage jusqu'à ce que vous publiez des détails sur la procédure stockée.

Amit Rai Sharma
la source
La procédure stockée ne fait rien d'extraordinaire. Cependant, il semble que la table OnlineUsers soit verrouillée pendant l'exécution de la procédure. Essayez le profileur SQL pour voir ce qui se passe à Application_Start
Amit Rai Sharma
2

essayer

EXEC SP_CONFIGURE 'remote query timeout', 1800
reconfigure
EXEC sp_configure

EXEC SP_CONFIGURE 'show advanced options', 1
reconfigure
EXEC sp_configure

EXEC SP_CONFIGURE 'remote query timeout', 1800
reconfigure
EXEC sp_configure

puis reconstruisez votre index

maksoud
la source
8
Pouvez-vous expliquer votre solution?
Hp93
0

Le délai a expiré car la requête sql prend plus de temps que vous n'en avez défini dans la propriété sqlCommand.CommandTimeout.

Évidemment, vous pouvez augmenter CommandTimeout pour résoudre ce problème, mais avant de le faire, vous devez optimiser votre requête en ajoutant un index. Si vous exécutez votre requête en studio de gestion de serveur Sql , y compris le plan d'exécution réel puis studio de gestion de serveur Sql vous proposera l' index approprié. Dans la plupart des cas, vous vous débarrasserez du problème de délai d'attente si vous pouvez optimiser votre requête.

Khabir
la source
0

TLDR :

  1. Le redémarrage des serveurs d'applications et de bases de données est la solution la plus rapide lorsque le volume de données, les paramètres réseau et le code n'ont pas changé. Nous le faisons toujours en règle générale
  2. Peut être un indicateur de défaillance du disque dur qui doit être remplacé - consultez les notifications système

J'ai souvent rencontré cette erreur pour diverses raisons et j'ai eu différentes solutions, notamment:

  1. refactoring de mon code pour utiliser SqlBulkCopy
  2. augmenter les valeurs de délai d'attente, comme indiqué dans diverses réponses ou vérifier les causes sous-jacentes ( peut ne pas être lié aux données )
  3. Délai d'expiration de la connexion (par défaut 15 s) - Combien de temps il faut attendre qu'une connexion soit établie avec le serveur SQL avant de se terminer - liée à TCP / PORT - peut passer par une liste de contrôle de dépannage (article MSDN très pratique)
  4. Délai d'expiration de la commande (par défaut 30 s) - Combien de temps il faut pour attendre l'exécution d'une requête - Exécution de la requête / liée au trafic réseau - a également un processus de dépannage (un autre article MSDN très pratique)
  5. Redémarrage du ou des serveurs - à la fois l'application et le serveur DB (s'ils sont séparés) - où le code et les données n'ont pas changé, l'environnement doit avoir changé - La première chose que vous devez faire. Généralement causé par des correctifs (système d'exploitation, .Net Framework ou correctifs ou mises à jour SQL Server). En particulier si une exception de délai d'attente apparaît comme ci-dessous (même si nous n'utilisons pas Azure):
    • System.Data.Entity.Core.EntityException: une exception a été déclenchée, probablement en raison d'une défaillance transitoire. Si vous vous connectez à une base de données SQL Azure, envisagez d'utiliser SqlAzureExecutionStrategy. ---> System.Data.Entity.Core.EntityCommandExecutionException: une erreur s'est produite lors de l'exécution de la définition de commande. Voir l'exception interne pour plus de détails. ---> System.Data.SqlClient.SqlException: une erreur au niveau du transport s'est produite lors de la réception des résultats du serveur. (fournisseur: fournisseur TCP, erreur: 0 - Le délai d'expiration du sémaphore a expiré.) ---> System.ComponentModel.Win32Exception: le délai d'expiration du sémaphore a expiré
user919426
la source
0

Assurez-vous également que vous n'avez pas de transaction en attente. :)

Je faisais des tests et j'ai commencé une transaction pour être sûre mais je ne l'ai jamais clôturée. Je souhaite que l'erreur aurait été plus explicite mais bon!

jeromej
la source
0

Nous avons eu des moments difficiles Timeout expired/max pool reached Sqlexception. Pour contourner le problème et pour empêcher le redémarrage du serveur ou du service, nous modifions la MAX SERVER MEMORYvariable dans SQL Server (via SQL Managment Studio ou T-SQL):

DECLARE @maxMem INT = 3000 --Max. memory for SQL Server instance in MB
EXEC sp_configure 'show advanced options', 1
RECONFIGURE

Cela résout temporairement le problème jusqu'à ce qu'il se reproduise. Dans notre cas, nous soupçonnons qu'il s'agit de fuites de connexion au niveau de l'application.

Santiago quitte SO
la source
0

Nous avons récemment mis à niveau vers la version NuGet de SqlClient( Microsoft.Data.SqlClient) qui contient un bogue . Ce bogue a été introduit pendant la durée de vie du cycle 1.x et a déjà été corrigé. Le correctif sera disponible dans la version 2.0.0 qui n'est pas disponible au moment d'écrire ces lignes. Un aperçu est disponible.

Vous pouvez consulter les détails ici: https://github.com/dotnet/SqlClient/issues/262

Noel Widmer
la source