【问题标题】:SQL Server Physical Memory Grow After Execution of CommandsSQL Server 物理内存在执行命令后增长
【发布时间】:2010-01-21 17:20:54
【问题描述】:

我正在使用 SQL Server 2008 在 Windows Server 2008 上运行服务器应用程序,现在我的方案是给定的。

  1. 我已经实现了一个自定义连接池(我为什么要这样做,这是另一个长篇大论)。因此我不会在每个请求上打开或关闭连接。

  2. 服务器应用程序使用池中可用的 10 个连接在一分钟内执行数千个 DBCommand。

  3. 在执行命令之后,我没有清理连接(因为我不知道要清理什么以及如何在不关闭和重新打开它的情况下清理),而且我没有处理命令对象本身。

  4. 当服务器应用程序关闭时,它会通过调用它们的 close 方法释放所有连接。

现在我观察到在 sqlserver 的 1 小时或 2 个进程的测试后,大约 3Gig 内存,然后我关闭了我的服务器应用程序,即使占用的内存没有释放或减少(根据任务管理器和资源监视器)毕竟我重新启动了sqlserver以释放内存。

下面是我的问题。

  1. 我是否需要每次都调用 DBCommand 对象的 Dispose,如果是,那么它会对连接对象产生影响。

  2. 上面提到的问题是我观察到的还是有其他原因。

  3. 有什么方法可以在不关闭连接的情况下清理连接,以及每次执行 DbCommand 后需要清理哪些垃圾。

谢谢 穆巴沙尔

【问题讨论】:

  • 实现自定义连接池是我书中的核心内容。如果您需要询问 IDispose,那么我不会编写自定义池。
  • 以下段落被添加为答案,但不是我在此处添加它作为对我原来问题的评论的答案。好吧,我查看了代码,发现我在命令对象上使用了“Using”语句,如下所示 using (DbCommand command = connectionAdoptor.GetDbCommand()) { //...bla bla bla } 它会自动调用 dispose 即使命令在其他函数上分配内存,如上述语句 GetDBCommand 正在初始化命令对象并返回引用。我对吗????问候穆巴沙

标签: .net sql-server-2008 dispose idbcommand


【解决方案1】:

然后我关闭了我的服务器应用程序,即使占用的内存没有释放或减少(根据任务管理器和资源监视器)[...]

由于关闭您的应用程序会释放所有对象,因此这一观察清楚地表明,内存丢失问题不是由您的对象未释放引起的。 (尽管如此,正如 David 正确指出的那样,始终处置 IDisposables 是一种很好的做法。)

因此,您应该查看 SQL Server 的内存配置。请注意,如果内存可用,则使用该内存的 SQL Server 是一件好事。未使用的内存是浪费钱。通常,SQL Server frees memory once some other process 需要它:

当 SQL Server 动态使用内存时,它会定期查询系统以确定可用的空闲物理内存量。 SQL Server 根据服务器活动增大或缩小缓冲区高速缓存,以将可用物理内存保持在 4 MB 和 10 MB 之间。这可以防止 Microsoft Windows NT® 4.0 或 Windows® 2000 分页。如果可用内存较少,SQL Server 会向 Windows NT 4.0 或 Windows 2000 释放通常在可用列表中的内存。如果有更多可用内存,SQL Server 会将内存重新提交到缓冲区高速缓存。 SQL Server 仅在其工作负载需要更多内存时才向缓冲区缓存添加内存;处于静止状态的服务器不会增加其缓冲区缓存。

因此,除非您的服务器开始过度交换,否则我不会过多担心 SQL Server 内存消耗。

【讨论】:

  • 感谢您的详细回答,这是我所期待的,但您能告诉我如何通过某种实验来检查 sql server 是否根据操作系统需求释放内存来确认这一点。谢谢问候穆巴沙
  • 这是个好问题。为了微调 SQL Server 内存消耗问题(即确定是否需要更多内存),我发现 SQL Server Performance Counters 非常有用,请参阅,例如这里:blogs.msdn.com/teekamg/archive/2007/11/06/…。您可以启动一个占用大量内存的小程序并检查 SQL Server 性能计数器以查看实际内存使用量是否减少。
【解决方案2】:

SQL Server 将使用大量内存,并且在必要时才将其归还,因此您应该始终在专用机器上运行 SQL。如果您必须在共享环境中使用它,您可以配置最大内存限制,但您的应用程序不会导致 SQL 释放内存。

【讨论】:

    【解决方案3】:
    1. 总是Dispose()IDispose-ables。

    2. 不知道。

    3. 使用sp_reset_connection 重置连接,然后再将其返回到池中。

    【讨论】:

    • 它的 sql server 是内置的 proc 对吗?好吧,我会尝试在谷歌上探索它,但是如果它的成本等于关闭/打开连接,那么你能告诉我它的成本是多少,那么我建立连接池的所有努力都将付诸东流。请尽快回复。问候穆巴沙
    • @mubashar:是的,它是内置的。阅读链接的问题和接受的答案以了解它的作用。进行适当的基准测试以确定特定硬件和工作负载的性能。
    【解决方案4】:

    控制连接池,并将参数传递给连接字符串,该字符串基本上包含以下内容:

    · 连接超时

    · 最小池大小

    · 最大池大小

    · 池化

    如果您发现您的应用程序在很短的时间内生成了大量的连接,那么您首先检查您的应用程序是否有打开的连接,并确保在完成处理后立即关闭它们。关闭的连接实际上不会关闭,并且可供服务器的另一个请求使用。特别检查您的 DataReader 对象并在它们脱离上下文时立即关闭它们。有时,开发人员在嵌套循环中使用多个 DataReader 并在 finally 子句中关闭所有 DataReader。不要这样做,一旦退出循环就尝试停止 DataReader。是的,您可以随时在 finally 子句中再次检查 DataReader 对象的状态,如果没有关闭,您可以关闭它。

    现在检查将 ConnectTimeout 调整到最小值,比如 1 秒。这会设置应用程序关闭的池中连接的生命周期,并将 MaxPoolSize 设置为服务器的最大限制。我猜,如果没有其他应用程序连接到同一个服务器数据库,它将是 100。将 MinPoolSize 值设置为 5,因为您会将 ConnectTimeOut 设置为最小值,在这种情况下,连接池要高效工作,您需要一些始终可用的连接。

    尝试这些设置和更改。希望这会让您满意。

    谢谢,

    拉吉夫·兰詹·拉尔

    【讨论】:

    • 我没有使用 SQL Server 或 ADO.Net 的连接池,我有自己的类,连接限制设置为 10,所有这些都在服务器启动时初始化,当服务器关闭时所有连接都断开下。但是有一些连接恢复和测试线程可能会导致连接在应用程序生命周期中打开或关闭。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2013-06-21
    • 1970-01-01
    • 2021-11-20
    • 2023-03-20
    • 1970-01-01
    • 2016-03-13
    • 1970-01-01
    相关资源
    最近更新 更多