超时已过期。操作完成之前经过的超时时间或服务器没有响应。该语句已终止

时间:2011-12-22 10:15:02

标签: c# asp.net sql-server-2008-r2 timeout sqlcommand

我的网站上有很多用户(每天20000-60000),这是一个移动文件的下载站点。我可以远程访问我的服务器(Windows Server 2008-R2)。
我之前收到"服务器不可用" 错误,但现在看到连接超时错误。
我对此并不熟悉 - 为什么会发生这种情况,我该如何解决?

完整错误如下:

  

' /'中的服务器错误应用。超时已过期。超时期限   在完成操作之前经过或服务器没有经过   响应。该语句已终止。描述:一个   在执行当前Web期间发生了未处理的异常   请求。请查看堆栈跟踪以获取有关的更多信息   错误以及它在代码中的起源。

     

异常详细信息:System.Data.SqlClient.SqlException:Timeout   过期。在完成之前经过了超时时间   操作或服务器没有响应。声明一直如此   终止。

     

来源错误:

     

执行期间生成了未处理的异常   当前的网络请求。有关的来源和位置的信息   可以使用下面的异常堆栈跟踪来识别异常。

     

堆栈追踪:

     

[SqlException(0x80131904):超时已过期。超时期限   在完成操作之前经过或服务器没有经过   响应。声明已经终止。]   System.Data.SqlClient.SqlConnection.OnError(SqlException异常,   Boolean breakConnection)+404
  System.Data.SqlClient.TdsParser.ThrowExceptionAndWarning()+412
  System.Data.SqlClient.TdsParser.Run(RunBehavior runBehavior,   SqlCommand cmdHandler,SqlDataReader dataStream,   BulkCopySimpleResultSet bulkCopyHandler,TdsParserStateObject   stateObj)+1363
  System.Data.SqlClient.SqlCommand.FinishExecuteReader(SqlDataReader ds,   RunBehavior runBehavior,String resetOptionsString)+6387741
  System.Data.SqlClient.SqlCommand.RunExecuteReaderTds(的CommandBehavior   cmdBehavior,RunBehavior runBehavior,Boolean returnStream,Boolean   异步)+6389442
  System.Data.SqlClient.SqlCommand.RunExecuteReader(的CommandBehavior   cmdBehavior,RunBehavior runBehavior,Boolean returnStream,String   方法,DbAsyncResult结果)+538
  System.Data.SqlClient.SqlCommand.InternalExecuteNonQuery(DbAsyncResult   result,String methodName,Boolean sendToPipe)+689
  System.Data.SqlClient.SqlCommand.ExecuteNonQuery()+ 327 7   NovinMedia.Data.DbObject.RunProcedure(String storedProcName,   IDataParameter []参数,Int32&受影响的行)+209
  DataLayer.OnlineUsers.Update_SessionEnd_And_Online(Object Session_End,   布尔在线)+440
  NiceFileExplorer.Global.Application_Start(Object sender,EventArgs e)   163

     

[HttpException(0x80004005):超时已过期。超时期限   在完成操作之前经过或服务器没有经过   响应。声明已经终止。]   System.Web.HttpApplicationFactory.EnsureAppStartCalledForIntegratedMode(HttpContext的   上下文,HttpApplication app)+405205​​3
  System.Web.HttpApplication.RegisterEventSubscriptionsWithIIS(IntPtr的   appContext,HttpContext上下文,MethodInfo []处理程序)+191
  System.Web.HttpApplication.InitSpecial(HttpApplicationState状态,   MethodInfo []处理程序,IntPtr appContext,HttpContext context)+352
  System.Web.HttpApplicationFactory.GetSpecialApplicationInstance(IntPtr的   appContext,HttpContext context)+407
  System.Web.Hosting.PipelineRuntime.InitializeApplication(IntPtr的   appContext)+375

     

[HttpException(0x80004005):超时已过期。超时期限   在完成操作之前经过或服务器没有经过   响应。声明已经终止。]   System.Web.HttpRuntime.FirstRequestInit(HttpContext context)+11686928   System.Web.HttpRuntime.EnsureFirstRequestInit(HttpContext context)   +141 System.Web.HttpRuntime.ProcessRequestNotificationPrivate(IIS7WorkerRequest)   wr,HttpContext context)+4863749


在回答后编辑:
Application_Start中的Global.asax如下所示:

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

    OnlineUsers.Update_SessionEnd_And_Online(
        DateTime.Now,
        false);

    AddTask("DoStuff", 10);
}

被调用的存储过程是:

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

我有两种获取在线用户的方法:

  1. 使用Application["OnlineUsers"] = 0;
  2. 另一个使用数据库
  3. 因此,对于方法#2,我重置Application_Start处的所有OnlineUser。该表中有超过482,751条记录。

22 个答案:

答案 0 :(得分:304)

看起来你的查询花费的时间超过了应有的时间。 从堆栈跟踪和代码中,您应该能够确切地确定查询是什么。

这种类型的超时可能有三个原因;

  1. 某处有死锁
  2. 数据库的统计信息和/或查询计划缓存不正确
  3. 查询过于复杂,需要调整
  4. 死锁可能很难解决,但很容易确定是否是这种情况。使用Sql Server Management Studio连接到数据库。在左窗格中,右键单击服务器节点,然后选择 Activity Monitor 。看看正在运行的进程。 通常大多数将闲置或运行。出现问题时,您可以通过进程状态识别任何阻止的进程。如果右键单击该流程并选择详细信息,它将显示该流程执行的最后一个查询。

    第二个问题将导致数据库使用次优查询计划。可以通过清除统计信息来解决:

    exec sp_updatestats
    

    如果这不起作用,您也可以尝试

    dbcc freeproccache
    

    当您的服务器负载很重时,不应该这样做,因为它会暂时产生很大的性能,因为所有存储过程和查询在首次执行时都会重新编译。 但是,由于您声明问题发生有时,并且堆栈跟踪指示您的应用程序正在启动,我认为您正在运行仅偶尔运行的查询。通过强制SQL Server不重用以前的查询计划,您可能会更好。有关如何执行此操作的详细信息,请参阅this answer

    我已经触及了第三个问题,但您可以通过手动执行查询(例如使用Sql Server Management Studio)轻松确定查询是否需要调优。如果查询需要很长时间才能完成,即使重置统计信息,您也可能需要对其进行调整。有关这方面的帮助,您应该在一个新问题中发布确切的查询。

答案 1 :(得分:138)

在运行存储过程的代码中,您应该具有以下内容:

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

添加以下代码:

c.CommandTimeout = 0;

这将等待操作完成所需的时间。

答案 2 :(得分:23)

您可以设置SQL命令的CommandTimeout属性以允许长时间运行的SQL事务。

您可能还需要查看导致超时的SQL查询。

答案 3 :(得分:12)

虽然所有早期的回复都解决了这个问题,但并没有涵盖所有案例。

Microsoft已承认此问题并在2011年针对受支持的操作系统进行了修复,因此如果您获得了如下堆栈跟踪:

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)

您可能需要更新.NET程序集。

  

由于连接重试中的错误,会出现此问题   镜像数据库的算法。

     

当使用重试算法时,数据提供者等待   第一次读取(SniReadSync)调用完成。呼叫被发送到   运行SQL Server的后端计算机,等待时间是   通过将连接超时值乘以0.08来计算。   但是,数据提供程序错误地设置了与注定的连接   如果响应缓慢且第一个SniReadSync调用不是,则表明状态   在等候时间到期之前完成。

有关详细信息,请参阅知识库文章2605597

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

答案 4 :(得分:9)

也许这对某些人有用。 我遇到了同样的问题,在我的情况下,原因是SqlConnection被打开而没有放在我用循环调用大约2500次迭代的方法中。连接池已用尽。正确的处理解决了这个问题。

答案 5 :(得分:6)

我在3天左右遇到同样的问题。我注意到我们的记录数量并不多,我们的高级开发人员在数据库中保留了2个图像和指纹。当我尝试获取这个十六进制值时需要很长时间,我计算执行我的程序的平均时间大约是38秒。默认的commandtimeout是30秒,因此它比运行我的存储过程所需的平均时间少。我将命令时间设置如下

cmd.CommandTimeout = 50

并且其工作正常,但有时如果您的查询超过50秒,则会提示相同的错误。

答案 6 :(得分:5)

您必须设置CommandTimeout属性。您可以在DbContext子类中设置CommandTimeout属性。

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; }
}

答案 7 :(得分:4)

我最近遇到了这个错误,经过一些简短的调查后发现原因是我们在占用数据库的磁盘空间不足(小于1GB)。

一旦我将数据库文件(.mdf和.ldf)移出到同一服务器上的另一个磁盘(具有更多空间),在三秒钟内加载超时的同一页面(运行查询)

在尝试解决此错误时,另一件需要调查的事情是数据库日志文件的大小。您的日志文件可能需要缩小。

答案 8 :(得分:3)

我在sp_foo中遇到大量计算的问题需要很长时间才能修复 用这个小位代码

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;
    }

答案 9 :(得分:2)

@SilverLight ..这显然是Database对象的问题。它可能是写得不好的查询,也可能是缺少索引。但截至目前,我不会建议您在不调查数据库对象问题的情况下增加超时时间

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

在这行代码上放置一个断点以找出过程名称,然后通过查看其执行计划来优化过程。

在您发布有关存储过程的详细信息之前,我无法帮助您。

答案 10 :(得分:2)

我遇到了同样的问题,并通过在web.config文件中添加“连接时间”值来解决。找到connectionStrings并添加 Connection Timeout = 3600“

这是示例

  <connectionStrings>
    <add name="MyConn" providerName="System.Data.SqlClient" connectionString="Data Source=MySQLServer;Initial Catalog=MyDB;User ID=sa;Password=123;Connection Timeout=3600" />
  </connectionStrings>

答案 11 :(得分:2)

如果您将ASP.NET Core与Startup.cs约定一起使用,则可以访问和设置查询命令超时选项,如下所示:

public void ConfigureServices(IServiceCollection services)
{
    services.AddDbContextPool<MyDbContext>(_ =>
    {
        _.UseSqlServer(Configuration.GetConnectionString("MyConnectionString"), options => 
        {
            options.CommandTimeout(180); // 3 minutes
        });
    });
}

答案 12 :(得分:1)

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

然后 重建你的索引

答案 13 :(得分:0)

我曾经遇到过这个问题,在我的例子中是 SQL 中的一个未提交的事务。我提交后,问题就解决了。

答案 14 :(得分:0)

我遇到了这个问题,当我将查询从 ADO.Net 转到 Dapper 时它就消失了。

答案 15 :(得分:0)

此外,您还需要检查逻辑中是否未更新单个记录,因为放置更新触发器也会导致超时错误。

因此,解决方案是确保在循环/光标之后执行批量更新,而不是在循环中一次执行一条记录。

答案 16 :(得分:0)

我们最近已升级到包含错误的SqlClientMicrosoft.Data.SqlClient)的NuGet版本。此错误是在1.x周期的生命周期中引入的,现已修复。该修补程序将在2.0.0版本中提供,在撰写本文时尚不可用。预览可用。

您可以在此处查看详细信息: https://github.com/dotnet/SqlClient/issues/262

答案 17 :(得分:0)

我们在Timeout expired/max pool reached Sqlexception上遇到了困难。作为一种解决方法,为防止重新启动服务器或服务,我们在SQL Server中修改了MAX SERVER MEMORY变量(通过SQL Managment Studio或T-SQL):

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

这可以暂时解决问题,直到再次发生。在我们的案例中,我们怀疑这与应用程序级别的连接泄漏有关。

答案 18 :(得分:0)

还要确保您没有待处理的交易。 :)

我当时正在做一些测试,为了安全起见开始了一笔交易,但从未关闭它。我希望该错误会更明确,但哦!

答案 19 :(得分:0)

TLDR

  1. 重新启动应用程序服务器和数据库服务器是最快的解决方案,其中数据量,网络设置和代码未更改。我们通常会这样做
  2. 可能表明需要更换的硬盘发生故障-检查系统通知

由于各种原因,我经常遇到此错误,并有各种解决方案,包括:

  1. 重构我的代码以使用SqlBulkCopy
  2. 增加超时值,如各种答案所述或检查 根本原因(可能与数据无关
  3. 连接超时(默认15秒)-终止之前等待与SQL Server建立连接所花的时间-与TCP / PORT相关的信息-可以通过a troubleshooting checklist(关于MSDN的便利文章)
  4. 命令超时(默认30秒)-等待查询执行需要多长时间-与查询执行/网络流量相关-also has a troubleshooting process(另一篇非常方便的MSDN文章)
  5. 重新引导服务器-应用程序和数据库服务器(如果分开)-代码和数据未更改,环境必须已更改-必须做的第一件事。通常由补丁程序(操作系统,.Net Framework或SQL Server补丁程序或更新)引起。特别是如果超时异常显示如下(即使我们不使用Azure):
    • System.Data.Entity.Core.EntityException:引发了一个异常,该异常可能是由于短暂故障所致。如果要连接到SQL Azure数据库,请考虑使用SqlAzureExecutionStrategy。 ---> System.Data.Entity.Core.EntityCommandExecutionException:执行命令定义时发生错误。有关详细信息,请参见内部异常。 ---> System.Data.SqlClient.SqlException:从服务器接收结果时发生传输级错误。 (提供者:TCP提供程序,错误:0-信号灯超时时间已过期。)---> System.ComponentModel.Win32Exception:信号灯超时时间已过期

答案 20 :(得分:0)

  

超时已过期,因为sql查询花费的时间超过了您设置的时间   在sqlCommand.CommandTimeout属性中。

     

显然,您可以增加CommandTimeout来解决此问题,但是   在此之前,您必须通过添加索引来优化查询。如果你   在 Sql服务器管理工​​作室中运行查询,包括实际   执行计划,然后 Sql Server Management Studio 会建议   您正确的索引。在大多数情况下,您将摆脱超时问题   如果您可以优化查询。

答案 21 :(得分:0)

默认超时为15秒,要进行更改,0是无限的,其他任何数字都是秒数。

代码内

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

在您的Web.Config中,“命令超时= 0;”不要超时,或少于1小时(3600秒)

  <add name="ConnectionString" connectionString="Data Source=ServerName;User ID=UserName;Password=Password;Command Timeout=3600;" providerName="System.Data.SqlClient" />