【问题标题】:Timeout expired. The timeout period elapsed prior to completion of the operation or the server is not responding. The statement has been terminated超时已过。在操作完成之前超时时间已过或服务器没有响应。该语句已终止
【发布时间】:2012-01-26 00:10:22
【问题描述】:

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

完整的错误如下:

“/”应用程序中的服务器错误。超时已过。超时时间 在操作完成之前已经过去,或者服务器没有 回应。该语句已终止。说明:一个 当前 web 执行过程中发生未处理的异常 要求。请查看堆栈跟踪以获取有关 错误及其源自代码的位置。

异常详细信息:System.Data.SqlClient.SqlException:超时 已到期。在完成之前超时时间已过 操作或服务器没有响应。该声明已 终止。

来源错误:

在执行过程中产生了一个未处理的异常 当前的网络请求。有关原产地和位置的信息 可以使用下面的异常堆栈跟踪来识别异常。

堆栈跟踪:

[SqlException (0x80131904): 超时。超时时间 在操作完成之前已经过去,或者服务器没有 回应。声明已终止。]
System.Data.SqlClient.SqlConnection.OnError(SqlException 异常, 布尔中断连接)+404
System.Data.SqlClient.TdsParser.ThrowExceptionAndWarning() +412
System.Data.SqlClient.TdsParser.Run(RunBehavior runBehavior, SqlCommand cmdHandler、SqlDataReader 数据流、 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、布尔 returnStream、布尔 异步)+6389442
System.Data.SqlClient.SqlCommand.RunExecuteReader(CommandBehavior cmdBehavior、RunBehavior、runBehavior、布尔返回流、字符串 方法,DbAsyncResult 结果)+538
System.Data.SqlClient.SqlCommand.InternalExecuteNonQuery(DbAsyncResult 结果,字符串方法名称,布尔值 sendToPipe) +689
System.Data.SqlClient.SqlCommand.ExecuteNonQuery() +327
NovinMedia.Data.DbObject.RunProcedure(字符串存储过程名称, IDataParameter[] 参数,Int32& rowsAffected) +209
DataLayer.OnlineUsers.Update_SessionEnd_And_Online(对象 Session_End, 布尔在线)+440
NiceFileExplorer.Global.Application_Start(对象发送者,EventArgs e) +163

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

[HttpException (0x80004005): 超时。超时时间 在操作完成之前已经过去,或者服务器没有 回应。声明已终止。]
System.Web.HttpRuntime.FirstRequestInit(HttpContext 上下文) +11686928 System.Web.HttpRuntime.EnsureFirstRequestInit(HttpContext 上下文) +141 System.Web.HttpRuntime.ProcessRequestNotificationPrivate(IIS7WorkerRequest WR,HttpContext 上下文)+4863749


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

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. 另一个使用数据库

因此,对于方法 #2,我将所有 OnlineUsers 重置为 Application_Start。该表中有超过 482,751 条记录。

【问题讨论】:

  • 正如这里所说的Default is 15 seconds
  • 最好进行根本原因分析,导致此类问题的原因有多种。最基本的是查询的复杂结构。当我获取在表中存储为十六进制值的图像时,我遇到了同样的问题。
  • 除了上面的原因,我再补充一个: 锁超时:docs.microsoft.com/en-us/sql/t-sql/statements/… 如果这个线程等待锁的时间过长,根据上面的文档会超时。
  • 在服务中重新启动 SQL Server 为我解决了这个问题。
  • 注意:此错误的另一个可能原因是如果您在 C#/VB.NET 代码中使用事务,然后调用从事务中访问数据库的其他函数/子程序。解决此问题的方法是将 db 传递给嵌套函数/子函数,以便将它们视为同一事务的一部分。 (注意:理想情况下,我建议不要在应用程序代码中执行事务;而是在 SQL 代码中执行。)

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


【解决方案1】:

看起来您的查询花费的时间比应有的要长。 从您的堆栈跟踪和代码中,您应该能够准确地确定查询是什么。

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

  1. 某处出现了僵局
  2. 数据库的统计信息和/或查询计划缓存不正确
  3. 查询太复杂,需要调优

死锁可能很难修复,但很容易确定是否是这种情况。使用 Sql Server Management Studio 连接到您的数据库。在左窗格中,右键单击服务器节点并选择 Activity Monitor。查看正在运行的进程。 通常大多数将处于空闲或运行状态。当问题发生时,您可以通过进程状态识别任何阻塞的进程。如果您右键单击该进程并选择详细信息,它将向您显示该进程执行的最后一个查询。

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

exec sp_updatestats

如果不行你也可以试试

dbcc freeproccache

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

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

【讨论】:

  • 我遇到了同样的错误,但在查询中“仅”花了 8 秒......您关于 exec sp_updatestats 的提示解决了我的问题。非常感谢!
  • 解决这样的问题几乎从来都不是调整超时或连接池大小的问题。您需要深入研究并找出根本原因。如果您需要帮助解决该根本原因,您可以发布您自己的问题。
  • 这当然不是死锁。可能是由于过度阻塞造成的,但是死锁在一秒钟内解决,它们会产生不同的错误。这可能是过度阻塞,但不是死锁。
  • 我们确定这是命令超时而不是连接超时吗? “System.Data.SqlClient.SqlConnection.OnError”对我来说表示连接问题。
  • @PrashantPimpale 视情况而定 如果您在生产中遇到严重的问题,即不正确的统计数据会导致执行计划错误,那么,是的,这可能是一个解决方案。除非出现异常问题(如硬件故障),否则更新统计信息不会破坏您的数据库。它可能会导致查询速度变慢一点。最后,这是你的电话。
【解决方案2】:

在您运行存储过程的代码中,您应该有这样的内容:

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

添加这样一行代码:

c.CommandTimeout = 0;

这将等待操作完成所需的尽可能长的时间。

【讨论】:

  • 您还应该知道,0 值不是recommended0 值表示没有限制,并且应该避免在 CommandTimeout 中,因为尝试执行命令会等待无限期。 最好了解命令需要​​多少时间,并在需要时增加 Timeout 值。
  • 我同意 Otiel 并否决了您的回答:将 commandTimeout 设置为 0 时,您不会让网络服务器有机会从不响应的数据库服务器中恢复。其次,当您达到默认超时时,您应该考虑查看原因。在大多数情况下,修复查询比提高超时时间更好。
  • 我不会陷入不推荐它的陷阱。这对我和我的日常计划任务非常有用:无限超时不会停止进程完成并在出现问题时返回错误。简单地说,它只是让您允许查询在需要时完成,而不会在以后给自己带来问题,因为您没有分配足够的时间来完成该过程。您还可以通过多线程来避免锁定您的程序。
  • 是的,对于大数据传输不设置这没有意义。如果您要传输数百万行,那么 Otiel 和 BlackHawkDesign 所说的就没有意义。
  • 在 20 年的以数据为中心的开发中,我从来不需要这样做。几乎总是有一个相当简单的解决方案可以提供更好的性能,并且不会为单个进程整天磨练数据库创造机会。绝大多数数据库性能问题都可以调整到它们的执行速度提高几个数量级。即,您等待 3 小时才能完成的过程可能会调整为 3 分钟甚至 3 秒。
【解决方案3】:

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

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

【讨论】:

  • 嗨,“或者您需要查看导致超时的 SQL 查询”-> 在 sql server 2008 中我应该在哪里检查该超时?
  • 您可能需要测试从 DataLayer.OnlineUsers.Update_SessionEnd_And_Online 调用的存储过程,因为堆栈跟踪似乎指向它。将实时数据库的副本进行测试并运行传递所需参数的存储过程,如果完成时间超过 30 秒,这就是您超时的原因。我假设您可以访问 SQL Server Management Studio。
  • 是的,我可以访问 sql server 2008。我应该试试你的方法。
  • 如果您发现导致问题的存储过程,您可以通过数据库优化顾问运行存储过程中包含的查询,它会建议您是否需要任何索引等。链接在这里msdn.microsoft.com/en-us/library/ms174202.aspx
【解决方案4】:

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

【讨论】:

  • 这个!正是这个。我的问题是我在不同的线程上触发了方法而不等待它们(因为用户不需要该方法的结果,后台脚本)。没有处理(利用using 块)我遇到了这个超时问题。这似乎解决了它。
  • 您是否收到超时错误,连接池已达到最大值或超时已过期。在操作完成之前超时时间已过或服务器没有响应。因为,如果您收到已达到的最大池,则查看泄漏的连接是有意义的。但是,我得到服务器没有响应错误。
【解决方案5】:

虽然之前的所有回复都解决了这个问题,但它们并未涵盖所有案例。

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 调用不是 在等待时间到期之前完成。

有关详细信息,请参阅 KB 2605597

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

【讨论】:

    【解决方案6】:

    您必须设置 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】:

      我遇到了同样的问题,并通过在 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>
      

      【讨论】:

        【解决方案8】:

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

        cmd.CommandTimeout = 50
        

        它工作正常,但有时如果您的查询时间超过 50 秒,它会提示同样的错误。

        【讨论】:

          【解决方案9】:

          如果您使用具有Startup.cs 约定的 ASP.NET Core,您可以像这样访问和设置查询命令超时选项:

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

          【讨论】:

            【解决方案10】:

            默认超时为 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" />
            

            【讨论】:

            • 这是两个不同的超时。您的第一个建议解决了这个问题。您的第二个仅在连接提供程序支持它时才有效,而 SqlClient 不支持。无论如何,0 超时在生产中绝不是一个好主意。 30 秒是通常的默认值。
            【解决方案11】:

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

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

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

            【讨论】:

              【解决方案12】:

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

              【讨论】:

                【解决方案13】:

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

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

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

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

                【讨论】:

                • 存储过程不做任何花哨的事情。但是,在执行过程时,似乎 OnlineUsers 表被锁定。尝试 SQL 探查器以查看 Application_Start 发生了什么
                【解决方案14】:

                试试

                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
                

                那么 重建你的索引

                【讨论】:

                • 您能解释一下您的解决方案吗?
                • 如何重建你的索引?
                【解决方案15】:

                TLDR

                1. 在数据量、网络设置和代码未更改的情况下,重新启动应用程序和数据库服务器是最快的修复方法。我们总是按照惯例这样做
                2. 可能表明硬盘驱动器出现故障需要更换 - 检查系统通知

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

                1. 重构我的代码以使用SqlBulkCopy
                2. 增加超时值,如各种答案或检查中所述 根本原因(可能与数据无关
                3. 连接超时(默认 15 秒)- 在终止之前等待与 SQL 服务器建立连接需要多长时间 - 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 Provider,错误:0 - 信号量超时期限已过期。)---> System.ComponentModel.Win32Exception:信号量超时期限已过期

                【讨论】:

                • 如何重构以使用 SqlBulkCopy ?
                【解决方案16】:

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

                我正在做一些测试并开始交易以确保安全但从未关闭它。我希望错误会更明确,但是哦!

                【讨论】:

                  【解决方案17】:

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

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

                  【讨论】:

                    【解决方案18】:

                    我曾经遇到过这个问题,在我的情况下是 SQL 中的未提交事务。我提交后,问题就消失了。

                    【讨论】:

                      【解决方案19】:

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

                      显然你可以增加 CommandTimeout 来解决这个问题,但是 在此之前,您必须通过添加索引来优化您的查询。如果你 在 Sql server management studio 中运行您的查询,包括 actual 执行计划然后Sql server management studio会建议 你正确的索引。大多数情况下,您将摆脱超时问题 如果您可以优化您的查询。

                      【讨论】:

                        【解决方案20】:

                        我们在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
                        

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

                        【讨论】:

                        • 最大服务器内存 ?? @maxMem 是什么?
                        【解决方案21】:

                        您还需要检查单个记录是否没有在逻辑中更新,因为该位置的更新触发器也会导致超时错误。

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

                        【讨论】:

                          【解决方案22】:

                          我遇到了这个问题,当我从 ADO.Net 移动到 Dapper 进行查询时,它就消失了。

                          【讨论】:

                            【解决方案23】:

                            正如其他人所说,问题可能与待处理的交易有关。 就我而言,我必须将 DbTransaction 变量作为 ExecuteScalar 方法中的参数发送,以便正确执行过程。

                            之前:

                            ExecuteScalar(command)
                            

                            之后:

                            ExecuteScalar(command, transaction)
                            

                            【讨论】:

                              猜你喜欢
                              • 2013-03-06
                              • 2015-12-21
                              • 2012-09-23
                              • 2011-10-08
                              • 2012-07-24
                              相关资源
                              最近更新 更多