sql-server-2008 - 帮助解决SqlException:在非负载情况下,连接超时超时

标签 sql-server-2008 timeout connection connection-timeout

我有一台托管我的网站的服务器,该网站的流量几乎为零。
每天有少数人(<20)进入该网站,一些RSS阅读器也订阅了我们发布的一些供稿。

几乎每天晚上,RSS阅读器都会在深夜打到我们,并得到一个异常(exception),该网站由于连接超时而无法连接到SQL Server。
这些细节非常怪异,所以我正在寻找可能的问题方面的帮助,因为我不知道从哪里开始。

我们正在Windows Server 2008上使用ASP.Net MVC,Entity Framework和SQL Server2008。这台机器是我们从一个不完全顶级的提供商处获得的专用设备,因此可能无法进行最佳配置,或者谁知道呢?其他。
盒子也很小,只有1Gb RAM,但它应该承担我们目前的负载...

我要复制下面的完整调用堆栈,但首先,我们要了解一些事情:

  • 当iTunes查询我们的网站时,总是会发生此错误。我相信这与任何事情都没有关系,但事实是我们只能从iTunes获得它。我最好的猜测是,发生这种情况的原因是,只有iTunes在晚上的那个时间询问我们,而没有其他人打我们。
  • 我们的理论之一是SQL Server和IIS争夺内存,其中之一正在由于不被使用而被分页到磁盘,并且当有人“唤醒”它时,从磁盘读取所有内容花费的时间太长。回到内存。这可能会发生吗? (我有点舍弃了它,因为如果可能的话,这听起来像是SQL Server中的一个设计问题)
  • 我也考虑过我们可能泄漏连接的可能性,因为我们可能没有适当地处置EF实体(see my question here)。这是我通过谷歌搜索问题可以发现的唯一东西。考虑到我们的负载极低,我将其丢弃。
  • 这总是在夜间发生,因此很可能与一段时间没有任何反应有关。例如,我非常确定当这些请求到达时,Web服务器进程将被回收,并且将启动/重新启动所有内容。但是,重新连接并不能解释SQL超时。


  • 更新:我们根据建议连接了探查器,并且花了一段时间才有了新的异常(exception)。这是我们知道的新内容:
  • 附加了探查器可以极大地减少我们得到的错误数量。实际上,在通常每天获得几次之后,我们不得不等待3或4天才能一次做到这一点。一旦我们停止了探查器,它就会回到正常的错误频率(甚至更糟)。因此,探查器具有某种效果,在某种程度上但并非完全隐藏了此问题。
  • 查看IIS请求日志旁边的探查器跟踪,请求和查询之间存在预期的1-1对应关系。但是,时不时地,我看到大量正在执行的查询与IIS日志完全没有关联。实际上,在记录实际错误之前,我在3分钟内就收到了 750个查询,所有这些都与IIS日志完全无关。查询文本看起来像是EF生成的那种不可读的废话,它们也不尽相同,它们看起来都像来自网站的查询一样:相同的ApplicationName,User等。是,在 2天的过程中,该站点收到了大约370个命中数据库的IIS请求
  • 这些无法解释的查询不是来自与以前的网站相同的ClientProcessID,尽管如果在此期间回收了流程,它们仍可能来自网站。在上一个解释的查询和第一个无法解释的查询之间几乎没有 Activity 一个小时。
  • 我不知道这些查询来自何处,这些较长的查询之一是在我记录错误之前发生的,因此我相信这是我们应该遵循的线索。
  • 正如我最初期望的那样,执行引发错误的查询时,它来自与上一个不同的ClientProcessID(比上一个无法解释的查询晚了8分钟,比上一个IIS的查询晚了几乎一小时)。对我来说,这意味着工作流程确实已经被回收了。
  • 这是我绝对不了解的东西。 IIS日志显示,在错误请求前一分钟,可以完美地处理4个请求,尽管对这些请求的查询根本没有出现在跟踪中。实际上,在这4个运行良好之后,我又连续抛出4个异常,这4个ALSO也没有出现在跟踪中(这很有意义,因为如果连接中存在超时,则查询永远都不会执行,但我也看不到跟踪中的连接尝试)

  • 简而言之,我对此一无所知。我找不到数百个快速连续运行的查询的原因,但我相信这些查询一定与问题有关。
    我也不知道如何诊断连接问题...
    或者探查器跟踪可能会丢失一些根据IIS进行的查询...

    有任何想法吗?

    这是异常信息:
    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)
    

    任何想法将不胜感激。

    最佳答案

    内存不足

    这很可能是一个内存问题,可能由于其他原因而加剧或触发,但本质上仍然是内存问题。还有其他两种(可能性较小)的可能性,您应该首先检查并消除(因为这样做很容易):

    易于检查的可能性:

  • 您可能启用了“自动关闭”:自动关闭可以完全具有这种行为,但是很少会打开它。要进行检查,请在SSMS中右键单击您的应用程序数据库,选择“属性”,然后选择“选项” Pane 。查看“自动关闭”条目,并确保将其设置为False。还要检查tempdb。
  • SQL代理作业可能是导致此问题的原因:检查代理的历史记录日志以查看事件期间是否有任何作业在持续运行。切记也要检查维护工作,因为诸如重建索引之类的东西在运行时经常被视为性能问题。这些现在不太可能成为候选对象,只是因为它们通常不会受到Profiler的影响。

  • 为什么看起来像是记忆问题:

    如果这些都不显示,则应检查内存问题。我怀疑内存是您的情况的原因,因为:
  • 您有1 GB的内存:尽管从技术上讲,这高于SQL Server的最低要求,但低于SQL Server的建议值,也低于我的经验(即使对于轻负载的服务器)也可以用于生产。
  • 您正在同一台机器上运行IIS和SQL Server:本身不建议这样做,这在很大程度上是因为争用了内存,但是只有1 GB的内存导致IIS,应用程序,SQL Server,操作系统以及任何其他任务和/或维护都需要占用很少的内存。 Windows管理此问题的方法是通过主动从非 Activity 进程中夺走内存,从而为 Activity 进程提供内存。一个大型进程(例如SQL Server)可能需要花费几秒钟甚至几分钟的时间才能获得足够的内存,以便在这种情况下能够完全为请求提供服务。
  • Profiler解决了90%的问题:这很可能是内存可能是问题的线索,因为通常情况下,像Profiler之类的东西确实对这个特定问题有影响:Profiler任务使SQL Server保持一点点活跃所有的时间。通常,这足以使它脱离操作系统的“清除剂”列表,或者至少在某种程度上降低了其影响。

  • 如何检查记忆作为罪魁祸首:
  • 关闭事件探查器:它会对问题产生海森堡效应,因此您必须将其关闭,否则将无法可靠地看到问题。
  • 从另一个框中运行系统监视器(perfmon.exe),该监视器远程连接到运行SQL Server和IIS的框中的性能收集服务。您可以最轻松地做到这一点,方法是先删除三个默认统计信息(它们仅是本地统计信息),然后添加所需的统计信息(如下所示),但请确保在第一个下拉列表中更改计算机名称以连接到SQL框。
  • 通过在perfmon上创建“计数器日志”,将收集的数据发送到文件。如果您不熟悉此方法,那么最简单的方法可能是将数据收集到一个选项卡或逗号分隔的文件中,然后可以使用Excel打开该文件进行分析。
  • 设置您的perfmon以将其收集到文件中并向其添加以下计数器:

    -处理器\处理器时间百分比[总计]

    -PhysicalDisk \%Idle Time [对于每个磁盘]

    -PhysicalDisk \ Avg。磁盘队列长度[每个磁盘]

    -内存\页面/秒

    -内存\页面读取数/秒

    -内存\可用兆字节

    -网络接口(interface)\总字节数/秒[对于使用中的每个接口(interface)]

    -处理\%处理器时间[见下文]

    -Process \ Page Faults / sec [请参见下文]

    -Process \ Working Set [见下文]
  • 对于进程计数器(上述),您想要包括sqlserver.exe进程,任何IIS进程以及任何稳定的应用程序进程。请注意,这仅适用于“稳定”过程。无法根据需要不断重新创建的进程无法通过这种方式捕获,因为无法在存在之前指定它们。
  • 在最经常发生问题的时间内,将此集合运行到文件中。将收集间隔设置为接近10到15秒。 (这会收集大量数据,但是您将需要此分辨率来挑选单独的事件)。
  • 在发生一个或多个事件后,请停止收集,然后使用Excel打开您的汇总数据文件。您可能必须重新格式化timestamp列,以使其有用并显示小时分钟和秒。使用IIS日志查找事件的确切时间,然后查看perfmon数据以查看事件之前和之后发生的事情。特别是,您要查看其工作集之前是否较小,之后是否较大,并且之间存在大量页面错误。这是这个问题的最明显迹象。

  • 解决方案:

    可以将IIS和SQL Server分别放在两个不同的框中(首选),或者在框中增加更多的内存。我认为3-4 GB应该是最小的。

    那奇怪的EF东西呢?

    这里的问题是,它很可能是外围问题,或者仅是主要问题的起因。请记住,探查器使您90%的事件消失了,所以剩下的问题可能是另一个问题,或者可能只是问题的最严重加剧。由于其行为,我想它可能正在循环其缓存或对应用程序服务器进程进行一些其他后台维护。

    关于sql-server-2008 - 帮助解决SqlException:在非负载情况下,连接超时超时,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/1421978/

    相关文章:

    sql - 如何从DBF文件转到SQL Server 2008?

    mysql - NHibernate:已经有一个与此连接关联的打开的 DataReader,必须先将其关闭

    postgresql - 无法从底层数据库获取 JDBC、Vertx、Postgresql 连接

    sql-server-2008 - 如何在 SQL 中使用 ROW_NUMBER() 更新列

    sql - 如何在订单中执行多个查询

    c# - 指定的强制类型转换无效 – SQL float to C# double

    linux - Ping 超时问题

    java - 从 URI 检索 RDF 时如何设置 HTTP 超时?

    ajax - 长时间运行的 Wicket Ajax 请求

    java - C3P0 ComboPooledDataSource getConnection() 是否始终返回有效的连接?