【问题标题】:Can low memory on IIS server cause SQL Timeouts (SQL Server on separate box)?IIS 服务器上的内存不足会导致 SQL 超时(单独框中的 SQL Server)吗?
【发布时间】:2013-01-15 21:08:48
【问题描述】:

我有一个 IIS Web 服务器,它托管 400 个 Web 应用程序(分布在 30 个应用程序池中)。它们都是 ASP.NET 应用程序和 WCF 服务端点。服务器有 32GB 的 RAM,通常运行速度很快;尽管它以 95% 的内存使用率运行。每个工作进程占用 500MB 到 1.5GB 的 RAM。

我还有另一个运行 SQL Server 的机器。那个有足够的可用内存。

有时,Web 服务器开始抛出 SQL 超时异常。起初每分钟几个,然后迅速增加到每分钟数百个;有效地使服务器停机。此问题会影响所有池中的应用程序。一些请求仍然完成,但大多数没有完成。虽然发生这种情况,但服务器上的 CPU 使用率约为 30%(这是该机器上的正常负载)。

虽然发生这种情况,但我们仍然可以使用 SQL Server Management Studio(来自 IIS 服务器)成功(并且快速)执行请求。

修复方法是重新启动 IIS。然后一切都恢复正常,直到下一次。

因为服务器运行时内存非常低,我觉得这就是原因。但是我无法解释低内存和突然爆发的 SQL Timeout 异常之间的关系。

有什么想法吗?

【问题讨论】:

  • 您是否确保您的 sql 连接被关闭并在代码中处理?有趣的场景。

标签: asp.net .net sql-server iis ado.net


【解决方案1】:

内存压力会触发分页和垃圾回收。两者都会引入延迟,否则不会出现。

GC 处理 32GB 数据可能需要几秒钟。为什么所有应用程序会同时处理 GC?因为在大约 95% 的内存利用率时,Windows 设置了 CLR 侦听的“low memory”事件。它将尝试释放内存以帮助其他进程。

如果应用程序陷入分页狂热,这也将解释正常执行中的巨大延迟。

不过,这只是猜测。您可以通过查看“Hard page faults/sec”计数器尝试证明它。还必须有一个用于“full GC”或“Gen 2 GC”的计数器。

修复将在物理内存限制的较高边际运行。

【讨论】:

  • 我们正在建立一个新的服务器来分担负载。之后,我希望两台服务器以 50% 的内存使用率运行。如果错误停止发生,我会断定它们是由内存压力引起的。如果错误继续发生,我将不得不继续寻找根本原因。我会告诉你的。
  • 我们将 40% 的应用程序移至另一台服务器。我遇到问题的服务器上的内存现在大约是 80%。此后没有出现意外的 SQL 超时异常。
  • 感谢您让我知道 - 即使是在问题完成 2 个月后!该理论现已得到证实。
【解决方案2】:

第一个问题是发现超时发生的位置。您能否从堆栈跟踪中判断超时是在执行对数据库的请求时发生,还是在连接到数据库时发生? (或者甚至连接到网络服务器?)

执行数据库请求的超时可能有多种原因。问题可能出在数据库中,有阻塞进程、数据库维护(也有锁)、死锁等。当应用程序运行缓慢时,您是否看到sys.dm_exec_requests 中有很多条目,如果有,它们的wait_types 是什么?

即使您可以在 Web 服务器超时时在查询窗口中运行 SQL,但这并不意味着不会发生大规模阻塞或死锁。

如果是超时连接到数据库,那么可能是 ADO 连接池不堪重负而没有被清理,或者数据库有连接限制,并且 Web 服务正在计时等待连接。

找出正在发生的事情的最佳方法之一是捕获 w3wp.exe 进程的内存转储并对其进行分析。即使您不擅长像 WinDbg 这样的调试器,Microsoft's DebugDiag tool 也可以生成一些包含有用信息的漂亮报告。

【讨论】:

    【解决方案3】:

    SqlCommand.CommandTimeout

    此属性是命令执行或结果处理期间所有网络读取的累积超时。返回第一行后仍有可能超时,不包括用户处理时间,只包括网络读取时间。

    这是基于客户端的超时。如果东西由于内存限制而排队,那么这可能会导致超时。

    您是否从这些查询中检索到大量数据?

    如果某些查询返回大量数据,请考虑将它们分解并为用户提供下一个和上一个按钮。

    您是否考虑过像 BeginExecuteReader 这样的异步?
    优点是没有超时。
    它不会释放调用线程。

    isExecutingFTSindexWordOnce = true;
    sqlCmdFTSindexWordOnce.BeginExecuteNonQuery(callbackFTSindexWordOnce, sqlCmdFTSindexWordOnce);
    // isExecutingFTSindexWordOnce set to false in the callback
    Debug.WriteLine("Calling thread active");
    

    但我同意您的评论如何响应请求,因为答案不会返回到调用线程。
    抱歉,我习惯了 WPF,我只是在回调时更新公共属性。

    【讨论】:

    • 1.大量数据:有些查询可以,有些查询不可以。涉及许多不同的应用程序。 2. BeginExecuteReader 将如何提供帮助?它会在 I/O 发生时释放 Web 请求线程。
    • 真的BeginExecuteReader会释放web请求线程吗?你测试了吗?
    • BeginExecuteReader 在执行 I/O 时释放调用线程。获取一个调用 BeginExecuteReader 的 Web 服务以在等待 BeginExecuteReader 时释放其调用线程(Web 请求)将需要额外的工作。我的观点是,我看不出异步 I/O 如何帮助解决我的问题。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-09-08
    • 2017-09-21
    • 2011-04-23
    相关资源
    最近更新 更多