【问题标题】:Will pooled SQL Connections be scavenged if there is still a reference to them?如果仍然有对它们的引用,是否会清除池化 SQL 连接?
【发布时间】:2012-09-30 19:27:04
【问题描述】:

@usr 和我是having a disagreement in another question 关于 .NET 是否会清除已空闲但仍保持保留引用的打开连接。

我坚持,based on documentation,如果物理连接空闲一段时间,即使 SQLConnection 对象引用保持保持,它也会在一段时间后被回收。

usr 声称这不会发生,它只回收不再有引用的连接。他的断言将使连接池变得不可靠,并且会对事务造成严重破坏。

我承认,文档对持有参考的问题含糊不清。

我正在寻找一个权威的答案,而不仅仅是猜测。要么有人已经试验并证明了这两种情况,要么是了解内部工作原理的人。

那是哪一个?

编辑:

我认为这里的混淆在于“关闭”的术语。情况似乎是文档将关闭物理连接称为从池中“删除”连接。而“关闭”是指将打开的物理连接释放回池中以供重复使用。

打开的连接仍然可以中止,但是如果客户端应用程序仍将其保持为打开状态(即客户端应用程序尚未在中止的连接上调用关闭),池程序是否将其标记为无效,但不确定它是否真的很重要,而不是作为池计数的一部分。

【问题讨论】:

  • 嗯,默认连接超时是 30 秒 - 超过这个超时将导致连接异常关闭并被池回收。但是,如果超时时间不受限制,则不会回收打开的连接。
  • @Oded - 我认为超时只是框架尝试连接的时间。不过,如果属实,它并不能真正解决问题。
  • 我可能正在考虑连接生命周期...
  • 您认为文档的哪一部分说空闲连接可以/将被回收?
  • @HenkHolterman - 删除连接部分。

标签: .net sql-server connection-pooling sqlconnection


【解决方案1】:

我可以 100% 肯定地告诉您,连接不会在释放之前返回到池中。我有一个会话创建一个临时表,并在等待用户输入时将其挂起。用户在 6 分钟后返回,按下按钮并继续在同一个 SPID 上继续使用临时表。

应用逻辑,这是有道理的,因为您能想象如果您因为闲置 X 分钟而丢失 SPID 会造成严重破坏吗?您是否应该继续使用命令“ping”SQL Server 以使其保持活动状态? (这太疯狂了


您似乎混淆了两个概念。当连接关闭时,它会返回到池中。如果超出范围,则隐式关闭 -> 返回池。对“空闲”的引用是指连接在池中变为空闲时,而不是当它被主动引用且未关闭时。持有的连接甚至不在池中,无法进行任何类型的清理。从池中释放资源是有道理的,因为一个 Web 应用程序可以很容易地爆发到 100 个连接,然后在接下来的几个月里保持大约 20 个左右的活动并发连接。

【讨论】:

  • 我认为这里的混淆在于“关闭”的术语。情况似乎是,文档将关闭物理连接称为从池中“删除”连接。而“关闭”是指将打开的物理连接释放回池中以供重复使用。
【解决方案2】:

.NET 是否会清除已打开的空闲连接,但仍会保持一个持有的引用

“持有的参考”在这里无关紧要,重点是“开放”。要正确回收连接,您需要 Dispose()Close() 它。

【讨论】:

  • 您并没有完全理解这个问题的微妙之处。问题在于连接池清理系统。
  • 这个清除系统是什么/在哪里?您链接到的页面没有提及。
  • "连接池会定期扫描连接池,寻找没有被 Close 或 Dispose 关闭的未使用连接,并回收它找到的那些"
  • 是的,你是对的。但是“未使用”的定义不是很好。最好在问题的顶部引用该部分。
【解决方案3】:

我刚刚运行了以下程序:

        var conn = new SqlConnection("...");
        conn.Open();
        conn.ExecuteNonQuery("select null");
        Thread.Sleep(TimeSpan.FromMinutes(11));
        conn.ExecuteNonQuery("select null");

它成功运行(使用自定义辅助方法,因此您无法直接运行它)。

这当然不能证明任何事情(仅当它没有正确运行时)。反射器显示池在 6.5 分钟后第一次清理,此后每 30 秒清理一次:

private Timer CreatePruningTimer()
{
    return new Timer(new TimerCallback(this.PruneConnectionPoolGroups), null, 240000, 30000);
}

所以测试应该已经暴露了问题。

现在,文档中的句子不是特别清楚。它没有提到 GC 甚至对象引用(在你的问题中你说有,但它没有)。

连接池程序会定期扫描连接池以查找 未通过 Close 或 Dispose 关闭的未使用连接,以及 回收它找到的那些。如果您的应用程序没有明确关闭 或处置其连接,它可能需要相当长的时间 连接池回收它们,所以最好确保你 在您的连接中显式调用 Close 和 Dispose。

我不相信它。用贝叶斯术语来说,Microsoft 文档是强有力的证据,但如果有强有力的反证,人们可能会得出相反的结论。

我有以下证据表明打开的连接不会无故关闭:

  1. 这会注入无法预防的随机故障(只能通过重试)
  2. 它会中止正常的交易
  3. 这将使长时间运行的事务变得不可能
  4. 我看不出为什么会出现这种情况的原因
  5. 文档中的语句可以按以下方式解释:池定期返回尚未关闭但其相应 SqlConnection 对象已被 GC 处理的连接(通过使用 Wea​​kReference 或其他方式检测)。我猜微软文档作者的意思是,或者不理解这个问题(似是而非!)
  6. 测试没有证明问题
  7. SSMS 如何管理运行长达一小时的查询? SSMS 应受到同样的限制

【讨论】:

  • GC 调用 finalize,关闭连接。所以#5并没有太多的snese。长达一小时的查询不会闲置。
  • 那句话措辞很糟糕。我把它清理干净了。
猜你喜欢
  • 1970-01-01
  • 2020-09-20
  • 2016-07-29
  • 2010-10-04
  • 1970-01-01
  • 1970-01-01
  • 2018-03-20
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多