【问题标题】:ODP.NET: Avoiding Connection Timeouts with Connection PoolingODP.NET:使用连接池避免连接超时
【发布时间】:2010-12-09 14:22:27
【问题描述】:

在一个站点上,我可以使用 SQL Developer 连接到 Oracle 数据库,让它闲置很长时间(例如,> 60 分钟),然后返回,就可以了。在第二个站点,如果它闲置超过 5-10 分钟(我没有准确计算),它会使 SQL Developer 处于新操作将超时的状态,我需要手动“断开连接”,然后按顺序重新连接做任何有用的事情。这似乎是第二个站点的连接超时,我不知道是什么原因造成的(我想知道如何关闭它,尽管这不是我的主要问题)。

我的程序使用 ODP.NET 并处理突然出现的数据。每 30 分钟(为了讨论)它会得到一堆数据来处理,这将涉及到一些重复的连接。它还使用连接池。我已将连接池设置为使用 5 分钟的生命周期。

我在第二个站点(而不是第一个站点)看到的是,我的程序会在每次数据突增开始时出现连接超时异常(例如 ORA-03113)。我相信正在发生的是,在数据激增期间,连接池按设计使用。在冲刺结束时检查“连接生命周期”,并且连接不是太旧,所以它留在连接池中。然后,30 分钟后,当新数据到达时,连接被从池中取出(并且不检查生命周期或超时)并使用,并且正在超时,就像我在 SQL Developer 中看到的那样。

如何避免连接超时,但仍能在突飞猛进期间利用连接池?从文档(和我的经验)看来,连接仅在进入池时检查生命周期,而不是在它出来时。

【问题讨论】:

  • 对这些问题不够了解,但我们遇到了一个非常相似的问题(更改了数据中心)。新的数据中心将杀死任何开放时间超过 X 分钟的无活动端口(我们遇到了与您在 SQL Developer 和其他长时间运行的进程中遇到的完全相同的问题。我们拒绝托管公司。他们结束了不要杀死 ora 端口(但他们简短地建议我们为 ora 连接实施一个脉冲,但被立即拒绝)但这需要他们的工作。祝你好运!

标签: .net oracle connection-pooling odp.net


【解决方案1】:

这是一个非常古老的问题,但我在应用程序中遇到了一些类似的问题,因此我认为其中一些信息可能会对遇到此问题的其他人有所帮助。

TL;DR 总结是 ODP.NET 驱动程序和 .NET 实现不能很好地相互配合,因此您正常运行的磨机连接池设置似乎无法完全按照您的预期工作。

  • Connection Lifetime 是主要违规者。我不确定this blog 是否仍然适用,因为它已经很老了,但我还没有找到任何文档来反驳它,它似乎可以验证我所看到的行为。根据博客,连接生命周期确实会按预期终止旧会话,但仅在调用数据库时才会检查此参数。所以换句话说,长时间运行的空闲会话永远不会被 .NET 杀死。
  • 如果您在 Oracle 用户配置文件中将IDLE_TIME 设置为一个值(而不是UNLIMITED),那么最终这些长时间运行的空闲参数将被数据库设置为SNIPED。这最终可能会导致 .NET 端出现问题,因为除非您明确检查您的连接是否仍然打开,否则 .NET 将提供这些 SNIPED 连接,就好像它们仍然可用一样(从而引发上述超时 ORA 错误)。
  • 解决这个问题的诀窍是确保您的连接字符串中有Data Validation=True;。这可确保 .NET 在为下一次服务调用提供连接之前检查会话连接。当此验证发现 SNIPED 会话时,会将其从 .NET 连接池中删除。

鉴于此信息,很可能 OP 的原始问题仅出现在一个站点中,由不同的数据库设置和/或 .NET 调用数据库的频率组合而成。他可能在这两种环境中都遇到了问题,但如果一个环境中的用户拨打电话的频率足以让Connection Lifetime 完成这项工作,那么他将永远不会在该数据库中看到这些超时。

现在我还没有弄清楚如何在任何 Oracle IDLE_TIME 狙击发生之前在 .NET 中终止空闲连接,但只要您使用 Data Validation = True 参数,您应该能够解决这个问题。

【讨论】:

    【解决方案2】:

    如果 5 分钟的 Lifetime 设置在第一个站点中运行良好,那么我认为这可能是由于有人在 Oracle 服务器端的 Profile 中设置了空闲会话超时造成的。

    然而,使用 5 分钟生命周期设置,当您的冲刺变得更大时,您可能仍会超时,因为当您在下一次冲刺中将连接返回到池时,它们会被破坏。然后池将忙于创建和删除连接,并且在负载非常大时可能导致连接超时。

    【讨论】:

      【解决方案3】:

      您可以通过将OracleCommand.ConnectionTimeout 属性设置为 0 来指定无限超时。 在这种情况下,不会有超时(至少在客户端)。

      在这种情况下也使用了ConnectionPool。

      【讨论】:

      • 谢谢 Tony,但我相信这个设置告诉 Oracle 等待响应的时间。我看到的问题是连接进入了永远不会得到响应的状态。所以这个设置可以避免异常,但我的程序仍然永远不会得到响应——所以我不认为这是一个解决方案。
      猜你喜欢
      • 2010-09-24
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-01-19
      相关资源
      最近更新 更多