Tempo limite expirado. O período de tempo limite decorrido antes da conclusão da operação ou o servidor não está respondendo. A instrução foi encerrada

296

Eu tenho muitos usuários no meu site (20000-60000 por dia), que é um site de download de arquivos para celular. Eu tenho acesso remoto ao meu servidor (Windows Server 2008-R2).
Já recebi erros "O servidor não está disponível" antes, mas agora estou vendo um erro de tempo limite de conexão.
Não estou familiarizado com isso - por que isso ocorre e como posso corrigi-lo?

O erro completo está abaixo:

Erro de Servidor na '/' Aplicação. Tempo limite expirado. O período de tempo limite decorrido antes da conclusão da operação ou o servidor não está respondendo. A instrução foi encerrada. Descrição: ocorreu uma exceção não tratada durante a execução da solicitação da web atual. Revise o rastreamento de pilha para obter mais informações sobre o erro e onde ele se originou no código.

Detalhes da exceção: System.Data.SqlClient.SqlException: Tempo limite expirado. O período de tempo limite decorrido antes da conclusão da operação ou o servidor não está respondendo. A instrução foi encerrada.

Erro de origem:

Uma exceção não tratada foi gerada durante a execução da solicitação da web atual. Informações sobre a origem e o local da exceção podem ser identificadas usando o rastreamento da pilha de exceções abaixo.

Rastreio de pilha:

[SqlException (0x80131904): tempo limite expirado. O período de tempo limite decorrido antes da conclusão da operação ou o servidor não está respondendo. A instrução foi finalizada.]
System.Data.SqlClient.SqlConnection.OnError (exceção SqlException, Boolean breakConnection) +404
System.Data.SqlClient.TdsParser.ThrowExceptionAndWarning () +412
System.Data.SqlClient.TdsParser.Run (RunBehavior , SqlCommand cmdHandler, SqlDataReader dataStream, BulkCopySimpleResultSet bulkCopyHandler, TdsParserStateObject stateObj) +1363
System.Data.SqlClient.SqlCommand.FinishExecuteReader (SqlDataReader2014)
System.Data.SqlClient.SqlCommand.RunExecuteReaderTds (CommandBehavior cmdBehavior, runBehavior runBehavior, booleano returnStream, assíncrono booleana) 6389442
System.Data.SqlClient.SqlCommand.RunExecuteReader (CommandBehavior cmdBehavior, runBehavior runBehavior, booleano returnStream, método de sequência, resultado DbAsyncResult) + 538
System.Data.SqlClient.SqlCommand.InternalExecuteNonQuery (resultado DbAsyncResult, String methodName, Boolean sendToPipe) +689
System.Data.SqlClient.SqlCommand.ExecuteNonQuery () +327
NovinMedia.Data.DbObject.RunProcedure (String, , Int32 & linesAffected) +209
DataLayer.OnlineUsers.Update_SessionEnd_And_Online (Object Session_End, Boolean Online) +440
NiceFileExplorer.Global.Application_Start (remetente do objeto, EventArgs e) +163

[HttpException (0x80004005): Tempo limite expirado. O período de tempo limite decorrido antes da conclusão da operação ou o servidor não está respondendo. A instrução foi encerrada.]
System.Web.HttpApplicationFactory.EnsureAppStartCalledForIntegratedMode (HttpContext contexto, HttpApplication app) 4052053
System.Web.HttpApplication.RegisterEventSubscriptionsWithIIS (IntPtr appContext, HttpContext contexto, MethodInfo [] manipuladores) 191
System.Web.HttpApplication. InitSpecial (estado HttpApplicationState, manipuladores MethodInfo [], IntPtr appContext, contexto HttpContext) +352
System.Web.HttpApplicationFactory.GetSpecialApplicationInstance (IntPtr appContext, contexto HttpContext) +407
System.Web.Host

[HttpException (0x80004005): Tempo limite expirado. O período de tempo limite decorrido antes da conclusão da operação ou o servidor não está respondendo. A instrução foi encerrada.]
System.Web.HttpRuntime.FirstRequestInit (contexto HttpContext) +11686928 System.Web.HttpRuntime.EnsureFirstRequestInit (contexto HttpContext) +141 System.Web.HttpRuntime.ProcessRequestNotificationPrivate (IIS7Worker)


EDITAR DEPOIS DAS RESPOSTAS:
meu Application_Startdentro Global.asaxé como abaixo:

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

    OnlineUsers.Update_SessionEnd_And_Online(
        DateTime.Now,
        false);

    AddTask("DoStuff", 10);
}

O procedimento armazenado que está sendo chamado é:

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

Eu tenho dois métodos para obter usuários online:

  1. usando Application["OnlineUsers"] = 0;
  2. o outro usando banco de dados

Portanto, para o método 2, redefino todos os usuários online em Application_Start. Existem mais de 482.751 registros nessa tabela.

Luz cinza
fonte
1
Como diz aqui O padrão é 15 segundos
V4Vendetta 22/12
1
Melhor fazer a análise da causa raiz. Existem várias razões para causar esse problema. O mais básico é a estrutura complexa de consulta. Eu enfrentei o mesmo problema ao buscar imagens armazenadas como valores hexadecimais na tabela.
Vijay Kumbhoje
Além das causas acima, adicionarei mais uma: Tempo limite do bloqueio: docs.microsoft.com/en-us/sql/t-sql/statements/… Se esse segmento aguardar muito tempo pelo bloqueio, o tempo limite será baseado em documento acima.
Herbert Yu

Respostas:

344

Parece que você tem uma consulta que está demorando mais do que deveria. No rastreamento da pilha e no código, você poderá determinar exatamente qual é a consulta.

Esse tipo de tempo limite pode ter três causas;

  1. Há um impasse em algum lugar
  2. As estatísticas do banco de dados e / ou o cache do plano de consulta estão incorretos
  3. A consulta é muito complexa e precisa ser ajustada

Pode ser difícil corrigir um impasse, mas é fácil determinar se é esse o caso. Conecte-se ao seu banco de dados com o Sql Server Management Studio. No painel esquerdo, clique com o botão direito do mouse no nó do servidor e selecione Activity Monitor . Dê uma olhada nos processos em execução. Normalmente, a maioria estará ociosa ou em execução. Quando o problema ocorre, você pode identificar qualquer processo bloqueado pelo estado do processo. Se você clicar com o botão direito do mouse no processo e selecionar detalhes, ele mostrará a última consulta executada pelo processo.

O segundo problema fará com que o banco de dados use um plano de consulta abaixo do ideal. Pode ser resolvido limpando as estatísticas:

exec sp_updatestats

Se isso não funcionar, você também pode tentar

dbcc freeproccache

Você não deve fazer isso quando o servidor estiver sob carga pesada, pois ocorrerá temporariamente uma grande ocorrência de desempenho, pois todos os procs e consultas armazenados serão recompilados quando executados pela primeira vez. No entanto, como você declara que o problema ocorre algumas vezes e o rastreamento da pilha indica que o aplicativo está sendo inicializado, acho que você está executando uma consulta que é executada apenas ocasionalmente. Pode ser melhor forçar o SQL Server a não reutilizar um plano de consulta anterior. Veja esta resposta para obter detalhes sobre como fazer isso.

Eu já falei sobre o terceiro problema, mas você pode determinar facilmente se a consulta precisa de ajuste executando a consulta manualmente, por exemplo, usando o Sql Server Management Studio. Se a consulta demorar muito para ser concluída, mesmo depois de redefinir as estatísticas, você provavelmente precisará ajustá-las. Para obter ajuda, você deve postar a consulta exata em uma nova pergunta.

Marnix van Valen
fonte
39
Eu estava tendo o mesmo erro, mas em uma consulta que 'apenas' levou 8 segundos ... e sua dica sobre o exec sp_updatestatsproblema foi resolvida. Muito Obrigado!
Nrod 27/02
2
Resolver um problema como esse quase nunca é uma questão de ajustar o tempo limite ou o tamanho do conjunto de conexões. Você precisará se aprofundar e descobrir a causa raiz. Se você precisar de ajuda para resolver essa causa raiz, poderá postar sua própria pergunta.
Marnix van Valen
5
Este certamente não é um impasse. Pode ser causado por bloqueio excessivo, mas os conflitos são resolvidos em um segundo e geram erros diferentes. Isso pode ser um bloqueio excessivo, mas não um impasse.
precisa
1
temos certeza de que este é um tempo limite de comando e não um tempo limite de conexão? "System.Data.SqlClient.SqlConnection.OnError" para mim indica um problema de conexão.
Mike W
1
@PrashantPimpale Depende Se você tiver um problema sério na produção em que estatísticas incorretas resultem em planos de execução incorretos, sim, isso pode ser uma solução. Salvo problemas excepcionais (como falha de hardware), a atualização de estatísticas não interromperá o seu banco de dados. Isso pode causar consultas mais lentas um pouco. No final, a decisão é sua.
Marnix van Valen
155

No seu código em que você executa o procedimento armazenado, você deve ter algo como isto:

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

Adicione essa linha de código:

c.CommandTimeout = 0;

Isso aguardará o tempo necessário para a operação ser concluída.

Elastep
fonte
143
Você também deve estar ciente de que o valor 0 não é recomendado : um valor de 0 indica sem limite e deve ser evitado em um CommandTimeout porque uma tentativa de executar um comando aguardará indefinidamente. É melhor aprender quanto tempo o comando leva e aumentar o valor do Tempo Limite, se necessário.
Otiel
7
Concordo com Otiel e diminuiu a sua resposta: Ao definir o commandTimeout como 0, você não dá ao servidor da web a chance de se recuperar de um servidor de banco de dados que não está respondendo. Em segundo lugar, ao atingir o tempo limite padrão, você deve considerar a causa. Na maioria dos casos, é melhor corrigir a consulta do que aumentar o tempo limite.
Maarten Kieft
10
Eu não cairia na armadilha de não recomendar. Tem sido muito útil para mim e minhas tarefas agendadas diariamente: Ter um tempo limite infinito não interrompe a conclusão do processo e retorna um erro se algo der errado. Simplificando, ele permite que uma consulta seja concluída sempre que for necessário, sem problemas futuros, porque você não havia alocado tempo suficiente para o processo terminar. Você também pode evitar o bloqueio do seu programa com vários threads.
WonderWorker
2
Sim, para transferências de dados grandes que não configuram isso não faz sentido. Se você estiver transferindo milhões de linhas, o que Otiel e BlackHawkDesign estão dizendo não faz sentido.
bluerubez
Em 20 anos de desenvolvimento centrado em dados, nunca precisei fazer isso. Quase sempre existe uma solução razoavelmente simples que oferece melhor desempenho e não cria uma oportunidade para um único processo trabalhar em um banco de dados o dia todo. A grande maioria dos problemas de desempenho do banco de dados pode ser ajustada para onde eles executam várias ordens de magnitudes mais rapidamente. Ou seja, esse processo que você está aguardando 3 horas para concluir, provavelmente pode ser ajustado para 3 minutos ou até 3 segundos.
b_levitt
25

Você pode definir a CommandTimeoutpropriedade do comando SQL para permitir a transação SQL de longa execução.

Você também pode precisar consultar a Consulta SQL que está causando o tempo limite.

Kev Ritchie
fonte
oi ", ou você precisa olhar para a consulta SQL que está causando o tempo limite" -> no sql server 2008, onde devo verificar esse tempo limite?
SilverLight
Pode ser necessário testar o procedimento armazenado chamado DataLayer.OnlineUsers.Update_SessionEnd_And_Online, pois o rastreamento de pilha parece apontar para ele. Faça uma cópia do banco de dados ativo em teste e execute o Procedimento Armazenado passando os parâmetros necessários, se levar mais de 30 segundos para concluir, é por isso que você está tendo um tempo limite. Suponho que você tenha acesso ao SQL Server Management Studio.
precisa
sim, tenho acesso ao sql server 2008. devo tentar do seu jeito.
SilverLight
Se você encontrar o procedimento armazenado que está causando o problema, poderá executar a consulta contida no procedimento armazenado através do Orientador de Otimização do Banco de Dados, que sugerirá se você precisa de índices etc. Link aqui msdn.microsoft.com/en-us/library /ms174202.aspx
Kev Ritchie
12

Embora todas as respostas anteriores tratem do problema, elas não cobriram todos os casos.

A Microsoft reconheceu o problema e o corrigiu em 2011 para os sistemas operacionais suportados. Portanto, se você receber o rastreamento de pilha, como:

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)

pode ser necessário atualizar seus assemblies .NET.

Esse problema ocorre devido a um erro no algoritmo de nova tentativa de conexão para bancos de dados espelhados.

Quando o algoritmo de nova tentativa é usado, o provedor de dados aguarda a conclusão da primeira chamada de leitura (SniReadSync). A chamada é enviada para o computador back-end que está executando o SQL Server e o tempo de espera é calculado multiplicando o valor do tempo limite da conexão por 0,08. No entanto, o provedor de dados define incorretamente uma conexão com um estado condenado se a resposta for lenta e se a primeira chamada SniReadSync não for concluída antes que o tempo de espera expire.

Consulte o KB 2605597 para obter detalhes

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

matcheek
fonte
9

Talvez seja útil para alguém. Eu enfrentei o mesmo problema e, no meu caso, o motivo foi o SqlConnection ter sido aberto e não descartado no método que chamei de loop com cerca de 2500 iterações. O pool de conexão estava esgotado. O descarte adequado resolveu o problema.

eternidade
fonte
isto! exatamente isso. Meu problema era que eu estava disparando métodos em um thread diferente sem esperar por eles (porque o usuário não precisa de um resultado desse método, script em segundo plano). Sem descartar (usando usingblocos), tenho esse problema de tempo limite. Isso pareceu resolver isso.
CularBytes 2/07
você recebeu o erro de tempo limite com o pool máximo de conexões atingido ou o tempo limite expirado. O período de tempo limite decorrido antes da conclusão da operação ou o servidor não está respondendo. Porque, se você receber o pool máximo atingido, faz sentido examinar a conexão vazada. mas, estou recebendo o servidor que não responde ao erro.
Jeeva Subburaj
8

Eu enfrentei o mesmo problema trabalhado nele em torno de 3 dias. Notei que nosso número de registros não é muito grande, pois nosso desenvolvedor sênior mantém 2 imagens e impressões digitais no banco de dados. Quando tento buscar esses valores hexadecimais, demorando muito tempo, calculo o tempo médio para executar meu procedimento em cerca de 38 segundos. O tempo limite do comando padrão é 30 segundos, portanto, é menor que o tempo médio necessário para executar meu procedimento armazenado. Defino meu commandtimeout como abaixo

cmd.CommandTimeout = 50

e está funcionando bem, mas às vezes, se sua consulta demorar mais de 50 segundos, o mesmo erro será solicitado.

Vijay Kumbhoje
fonte
8

Você precisa definir o atributo CommandTimeout. Você pode definir o atributo CommandTimeout na classe filho 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
fonte
4

Encontrei esse erro recentemente e, após uma breve investigação, descobri a causa: o espaço estava acabando no disco que contém o banco de dados (menos de 1 GB).

Assim que eu mudei os arquivos do banco de dados (.mdf e .ldf) para outro disco no mesmo servidor (com muito mais espaço), a mesma página (executando a consulta) que atingiu o tempo limite foi carregada em três segundos.

Outra coisa a investigar, ao tentar resolver esse erro, é o tamanho dos arquivos de log do banco de dados. Seus arquivos de log podem precisar ser reduzidos.

Hafiz Adewuyi
fonte
3

Eu tenho problema com o cálculo grande em sp_foo que leva muito tempo, então eu corrigi
com este pequeno código

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
fonte
3

O tempo limite padrão é de 15 segundos, para alterar isso, 0 é ilimitado, qualquer outro número é o número de segundos.

Em código

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

No seu Web.Config, "Tempo limite do comando = 0;" não exceda o tempo limite ou abaixo de 1 hora (3600 segundos)

  <add name="ConnectionString" connectionString="Data Source=ServerName;User ID=UserName;Password=Password;Command Timeout=3600;" providerName="System.Data.SqlClient" />
David C Fuchs
fonte
2
Esses são dois tempos limite diferentes. Sua primeira sugestão aborda a questão. Seu segundo funcionaria apenas se o provedor de conexão o suportasse, o que o SqlClient não suporta. De qualquer forma, um tempo limite de 0 nunca é uma boa ideia na produção. 30 segundos é o padrão usual.
Suncat2000
2

@ SilverLight .. Este é claramente um problema com um objeto de banco de dados. Pode ser uma consulta mal escrita ou índices ausentes. Mas, a partir de agora, não vou sugerir que você aumente o tempo limite sem investigar o problema com seus objetos de banco de dados

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

Coloque um ponto de interrupção nessa linha de código para descobrir o nome do procedimento e, em seguida, otimizar o procedimento, observando seu plano de execução.

Não posso ajudá-lo mais até o momento em que você publica detalhes sobre o procedimento armazenado.

Amit Rai Sharma
fonte
O procedimento armazenado não faz nada sofisticado. No entanto, parece que a tabela OnlineUsers está sendo bloqueada enquanto o procedimento está sendo executado. Tente profiler do SQL para ver o que está acontecendo em Application_Start
Amit Rai Sharma
2

experimentar

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

então reconstrua seu índice

maksoud
fonte
8
Você pode explicar sua solução?
Hp93
0

O tempo limite expirou porque a consulta sql está demorando mais tempo do que você define na propriedade sqlCommand.CommandTimeout.

Obviamente, você pode aumentar o CommandTimeout para resolver esse problema, mas antes de fazer isso, você deve otimizar sua consulta adicionando índice. Se você executar sua consulta no Sql server management studio, incluindo o plano de execução real , o Sql server management studio sugerirá o índice adequado. Na maioria dos casos, você se livrará do problema de tempo limite se puder otimizar sua consulta.

Khabir
fonte
0

TLDR :

  1. Reiniciar os servidores de aplicativos e de banco de dados é a solução mais rápida, onde o volume de dados, as configurações de rede e o código não foram alterados. Nós sempre fazemos isso como regra
  2. Pode ser um indicador de falha no disco rígido que precisa de substituição - verifique as notificações do sistema

Muitas vezes encontrei esse erro por vários motivos e tive várias soluções, incluindo:

  1. refatorando meu código para usar SqlBulkCopy
  2. aumentar os valores de tempo limite, conforme declarado em várias respostas ou verificar causas subjacentes ( pode não estar relacionado aos dados )
  3. Tempo limite de conexão (padrão 15s) - Quanto tempo leva para esperar que uma conexão seja estabelecida com o servidor SQL antes de terminar - relacionada ao TCP / PORT - pode passar por uma lista de verificação de solução de problemas (artigo muito útil do MSDN)
  4. Tempo limite do comando (padrão 30s) - Quanto tempo leva para aguardar a execução de uma consulta - Execução de consulta / tráfego de rede relacionado - também possui um processo de solução de problemas (outro artigo muito útil do MSDN)
  5. Reinicialização do (s) servidor (es) - aplicativo e servidor de banco de dados (se separados) - onde o código e os dados não foram alterados, o ambiente deve ter sido alterado - A primeira coisa a ser feita. Geralmente causado por patches (sistema operacional, .Net Framework ou patches ou atualizações do SQL Server). Especialmente se a exceção de tempo limite aparecer como abaixo (mesmo se não usarmos o Azure):
    • System.Data.Entity.Core.EntityException: uma exceção foi gerada provavelmente devido a uma falha transitória. Se você estiver se conectando a um banco de dados SQL Azure, considere usar SqlAzureExecutionStrategy. ---> System.Data.Entity.Core.EntityCommandExecutionException: ocorreu um erro ao executar a definição de comando. Consulte a exceção interna para obter detalhes. ---> System.Data.SqlClient.SqlException: ocorreu um erro no nível de transporte ao receber resultados do servidor. (provedor: TCP Provider, erro: 0 - O período de tempo limite do semáforo expirou.) ---> System.ComponentModel.Win32Exception: O período de tempo limite do semáforo expirou.
user919426
fonte
0

Verifique também se você não possui uma transação pendente. :)

Eu estava fazendo alguns testes e comecei uma transação para ser segura, mas nunca a fechei. Eu gostaria que o erro tivesse sido mais explícito, mas tudo bem!

jeromej
fonte
0

Tivemos tempos difíceis Timeout expired/max pool reached Sqlexception. Como solução alternativa, e para impedir a reinicialização do servidor ou do serviço, modificamos a MAX SERVER MEMORYvariável no SQL Server (por meio do 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

Isso corrige temporariamente o problema até que ocorra novamente. No nosso caso, suspeitamos que isso tenha a ver com vazamentos de conexão no nível do aplicativo.

Santiago deixa SO
fonte
0

Atualizamos recentemente para a versão NuGet do SqlClient ( Microsoft.Data.SqlClient) que contém um bug . Este bug foi introduzido durante a vida útil do ciclo 1.x e já foi corrigido. A correção estará disponível na versão 2.0.0, que não está disponível no momento desta redação. Uma visualização está disponível.

Você pode inspecionar os detalhes aqui: https://github.com/dotnet/SqlClient/issues/262

Noel Widmer
fonte