【问题标题】:Database connections not being closed on oracle serveroracle服务器上没有关闭数据库连接
【发布时间】:2016-05-20 05:34:59
【问题描述】:

我遇到了一个问题,当使用 NHibernate 连接到 Oracle11g 数据库时,池中的旧连接没有被关闭。

我相当确定所有 NHibernate 会话都已正确处理,但是连接仍保持在 INACTIVE 状态。我知道这将是因为连接池,但是在一定时间后应该将它们删除?如果不是,我该如何配置发生这种情况。

我已尝试将以下设置添加到我的连接字符串中:

Max Pool Size=10;
Connection Lifetime=120;
Incr Pool Size=1;
Decr Pool Size=10;`

这似乎停止创建尽可能多的连接,我猜是因为这个增加的大小是增量 1,但是一旦连接被放回池中,它们就永远不会关闭。

我查看了 v$session 表,其中一些 LASST_CALL_ET 值高达 786465 秒或 9 天!!

我很确定所有会话都已被处理,这是代码示例:

public class DoSomethingToDb(ISessionFactory sessionFactory)
{
  using (ISession session = sessionFactory.OpenSession())
  {
      session.Transaction.Begin();
      //Do Stuff
      session.Transaction.Commit();
  }
}

如何设置我的程序/NHibernate/Ado.Net/Oracle 以关闭不再使用的连接。

我们测试的服务器昨天崩溃了,因为有超过 800 个INACTVIE 连接,并且无法发出更多连接。

【问题讨论】:

    标签: c# oracle nhibernate ado.net connection-pooling


    【解决方案1】:

    您遇到问题的原因是您的 Decr Pool Size 值太大。除非所有连接都可以关闭,否则它将无法关闭任何连接,因为您的 Decr Pool Size 与您的 Max Pool Size 相同。

    当我将此值设置为 1 时,需要永远释放未使用的连接。我目前将我的设置为 5,每次递减之间仍然需要同样长的时间,但它会一次释放更多。

    Pooling=true; 
    Min Pool Size=0;
    Max Pool Size=10;
    Incr Pool Size=1;
    Decr Pool Size=3;
    

    此外,将 Connection Lifetime 设置为 120,它不会将任何会话保持打开超过 2 分钟。

    【讨论】:

      【解决方案2】:

      如果您可以在休眠状态下执行此操作,我会感到惊讶,因为我认为连接是泄漏的连接。由于某种原因,它们失去了控制,永远不会被重复使用。

      您可以在 Oracle 数据库的资源管理器中配置会话空闲超时。见Managing Resources with Oracle Database Resource Manager

      确保为您的池会话定义了一个资源使用者组,并且空闲超时足够大,不会意外中断正常工作的会话。

      Oracle 数据库资源管理器是一个非常灵活且功能强大的工具,可以在许多方面帮助您的系统。

      【讨论】:

      • 谢谢,我会调查的。 nhibernate 中是否存在会导致连接泄露的已知错误?或者这可能是我的应用程序中的错误?
      • 我不知道休眠,但据我所知,应用程序应该从池中选择一个连接并返回它,也在异常情况下。所以,是的,一个应用程序可能会出错,也许 hibernate 会处理它....我不知道。
      • 好的,这似乎是一个奇怪的问题,因为我们无法重新创建它。如果我们将 Max Pool Size 设置为 10,然后尝试打开 11 个连接,那么在打开第 11 个连接时,我们会得到预期的异常。目前我们似乎已经通过禁用连接池解决了这个问题,使用Pooling=false
      • 很难称其为解决方案...。这破坏了可伸缩性,因为数据库中的连接/断开连接操作是序列化的。这就是首先想要一个连接池的原因。
      • 没错,它也没有解决问题。一切正常运行 12 小时左右。然后连接处于非活动状态。
      【解决方案3】:

      问题似乎是由使用事务引起的。从上面的代码中删除事务产生了以下结果:

      public class DoSomethingToDb(ISessionFactory sessionFactory)
      {
        using (ISession session = sessionFactory.OpenSession())
        {
      
            //Do Stuff
            session.Flush();
        }
      }
      

      这似乎不会导致任何问题。

      【讨论】:

        猜你喜欢
        • 2014-09-11
        • 1970-01-01
        • 1970-01-01
        • 2019-05-24
        • 2018-03-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2011-03-26
        相关资源
        最近更新 更多