ODP.NET:使用连接池避免连接超时

dgenwo3n  于 2023-03-04  发布在  .NET
关注(0)|答案(4)|浏览(266)

在一个站点,我可以使用SQL Developer连接到Oracle数据库,让它长时间处于空闲状态(例如,〉60分钟),然后返回,就可以了。在第二个站点,如果闲置时间超过5-10分钟(我没数清楚),它使SQL Developer处于新操作将超时的状态,我需要手动“断开连接”,然后重新连接,以便执行任何有用的操作。这似乎是第二个站点的连接超时,我不知道是什么原因导致的(我想知道如何关闭它,尽管这不是我的主要问题)。
我的程序使用ODP .NET并处理突发的数据。每30分钟(为了便于讨论)它将得到一堆数据来处理,这将涉及到一些重复的连接。它也使用连接池。我已经设置连接池使用5分钟的生存期。
我在第二个地点看到的(不是在第一次)是我的程序将获得连接超时异常(例如,ORA-03113)。我相信正在发生的是,在数据突发期间,连接池按设计使用。在突发结束时,检查“连接寿命”,连接不是太旧,然后,30分钟后,当新数据到达时,连接将从池中取出(并且不检查生存期或超时)并使用,并且超时,就像我在SQL Developer中看到的那样。
如何避免连接超时,但仍能在突发期间利用连接池?从文档(以及我的经验)来看,似乎只有在连接进入池时才检查连接的生存期,而在连接出来时则不检查。

klr1opcd

klr1opcd1#

这是一个很老的问题,但我已经遇到了一些类似的问题与应用程序,所以我认为一些信息可能会帮助任何人谁绊倒在这个问题。
TL;DR的总结是,ODP .NET驱动程序和.NET实现不能很好地相互配合,因此您正常运行的普通连接池设置似乎并不完全按照您的期望工作。

*Connection Lifetime是主要攻击者。我不确定this blog是否仍然适用,因为它已经很旧了,但我还没有找到任何文档来反驳它,它似乎验证了我所看到的行为。根据博客,连接生存期确实会按预期终止较旧的会话,但仅在调用数据库时才检查此参数。换句话说,长时间运行的空闲会话永远不会被. NET杀死。

  • 如果将IDLE_TIME设置为Oracle用户配置文件中的值(而不是UNLIMITED),那么最终这些长时间运行的空闲参数将被数据库设置为SNIPED。这可能最终导致.NET端出现问题,因为除非您显式地检查连接是否仍然打开,.NET将提供这些SNIPED连接,就好像它们仍然可用一样(因此抛出上述超时ORA错误)。
  • 解决此问题的技巧是确保连接字符串中包含Data Validation=True;。这可确保.NET在为连接提供服务之前检查会话连接,直到下一个服务调用。当此验证发现SNIPED会话时,它会将其从.NET连接池中删除。

根据这些信息,OP的原始问题很可能是由于不同的数据库设置和/或对数据库的.NET调用频率的组合而仅出现在一个站点中。他可能在两个环境中都遇到了问题,但如果一个环境中的用户调用频率足以让Connection Lifetime完成其工作,那么他将永远不会在该数据库中看到这些超时。
现在,我仍然没有弄清楚如何在任何Oracle IDLE_TIME狙击发生之前在.NET中杀死一个空闲连接,但是只要您使用Data Validation = True参数,您应该有希望能够解决这个问题。

23c0lvtd

23c0lvtd2#

如果5分钟的生存期设置在第一个站点中运行良好,那么我认为这可能是由于有人在Oracle服务器端的配置文件中设置了空闲会话超时。
然而,使用5分钟的生存期设置,当你的突发变得更大时,你可能仍然会遇到超时,因为当你在下一次突发中将连接返回到池时,它们会被销毁。池将忙碌创建和删除连接,并可能在负载非常大时导致连接超时。

rqqzpn5f

rqqzpn5f3#

默认情况下,ODP. NET在连接池中始终创建并保持1个打开的连接。可以为Oracle Server配置服务器端连接超时,该超时将在一段时间后关闭空闲连接。如果应用程序长时间处于空闲状态,则可能会出现问题。因为当服务器自己关闭一个连接时,ODP.NET客户端并不知道连接已经关闭。客户端仍然在池中具有该连接,并将尝试使用它,然后您将得到一个错误。
有两种解决办法。
1.当使用ODP.NET连接池时,不要为连接设置服务器端空闲超时。如果你使用连接池,让服务器丢弃空闲连接确实没有多大意义。
1.如果你不能执行#1,那么你可以使用ODP. NET连接设置来设置MinPoolSize = 0。MinPoolSize = 0意味着当应用程序空闲时,ODP. NET客户端会让池中的连接数降为0。当应用程序必须再次工作时,这可能会影响性能,因为它将没有可用的连接来处理初始请求,而必须打开一个。但如果应用程序执行大量突发工作,其间有很长的空闲时间,那么这样做可能是有意义的。

oxcyiej7

oxcyiej74#

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

相关问题