2

我使用 Hibernate 3 和 postgres 开发的 Web 应用程序出现问题。问题是执行和提交的每个信号查询都不会释放池中的连接(限制 = 100)。在一个操作(SELECT、INSERT 等)之后,我对 DB 做了一些查询,得到了结果:

询问:

SELECT pid, query, state FROM pg_stat_activity;
5436;"SELECT...";"idle" <- 没关系
6776;"SELECT..." ;active" <- 没关系
5324;“提交”;“空闲”    
6840;“提交”;“空闲”    
6276;“提交”;“空闲”    
4804;“提交”;“空闲”    
5812;“提交”;“空闲”    
2608;“提交”;“空闲”    
2576;“提交”;“空闲”    
3896;“提交”;“空闲”    
4660;“提交”;“空闲”    
692;“提交”;“空闲”

如您所见,问题是提交的事务,它们留在连接池中并阻止它。接下来的操作会导致它不断增长,当池过量时我无法连接到数据库。我知道有一种方法可以手动删除它们(SELECT pg_terminate_backend()),但我更喜欢 Hibernate 中的解决方案。现在放开我的代码,也许它会清除。

这是我的 DBManager(执行查询和管理 DB 的类)中的方法示例:

public List getGroups()
{
    Session session = sessionFactory.openSession();
    List<Group> groups = new ArrayList<Group>();

    try
    {
        session.beginTransaction();
        groups = session.createQuery( "from Group WHERE locked='FALSE' ORDER BY startHours" ).list();
        session.getTransaction().commit();

    }
    catch ( Exception e )
    {
        // logs
    }
    finally
    {
        try
        {
            session.close();
        }
        catch ( Exception e )
        {
        }
    }

    return groups;
}

任何其他方法都以相同的方式完成。我的会话工厂是在类级别定义的:

  public class DBManager
  {

   SessionFactory sessionFactory = new Configuration().configure().buildSessionFactory();

    public DBManager()
    {

    }

     // METHODS HERE
  }

请告诉我我做错了什么...会话是通过打开和关闭的try{}catch{}finally{}。似乎在提交事务之后没有正确关闭。

这是我的hibernate.cfg:

    <!-- Database connection settings -->
    <property name="hibernate.connection.driver_class">org.postgresql.Driver</property>
    <property name="hibernate.connection.url">jdbc:postgresql://localhost:5432/szkola_plywania_test</property>
    <property name="hibernate.connection.username">postgres</property>
    <property name="hibernate.connection.password">postgres</property>

    <!-- JDBC connection pool(use the built-in) -->
    <property name="hibernate.connection.pool_size">1</property>

    <!-- SQL dialect -->
    <property name="hibernate.dialect">org.hibernate.dialect.PostgreSQLDialect</property>

    <property name="hibernate.connection.release_mode">after_statement</property>    

    <!-- Disable the second-level cache -->
    <property name="hibernate.cache.provider_class">org.hibernate.cache.NoCacheProvider</property>

    <!-- Echo all executed SQL to stdout -->
    <property name="hibernate.show_sql">true</property> <!-- wynik pokazywany w konsoli -->

    <!-- Drop and re-create the database schema on startup -->
    <property name="hibernate.hbm2ddl.auto">update</property> <!-- create - nadpisywanie, update - dopisywanie -->

    <property name="hibernate.show_sql">true</property>

 <property name="hibernate.c3p0.acquire_increment">1</property>
    <property name="hibernate.c3p0.idle_test_period">100</property> <!-- seconds --> 
    <property name="hibernate.c3p0.max_size">100</property> 
    <property name="hibernate.c3p0.max_statements">0</property> 
    <property name="hibernate.c3p0.min_size">10</property> 
    <property name="hibernate.c3p0.timeout">100</property> <!-- seconds -->

    <!-- Names the annotated entity class -->
    <mapping class="com.school.hibernate.dto.User" />
    <mapping class="com.school.hibernate.dto.MailConfig" />
    <mapping class="com.school.hibernate.dto.Group" />
    <mapping class="com.school.hibernate.dto.Child" />
    <mapping class="com.school.hibernate.dto.Term" />
    <mapping class="com.school.hibernate.dto.Counter" />
    <mapping class="com.school.hibernate.dto.Invoice" />
    <mapping class="com.school.hibernate.dto.AgeGroup" />
    <mapping class="com.school.hibernate.dto.GroupTerm" />
    <mapping class="com.school.hibernate.dto.Instructor" />
    <mapping class="com.school.hibernate.dto.PassInstance" />
4

1 回答 1

5

idle不是问题。它只是一个什么都不做的开放连接。

idle in transaction将是一个问题,因为这些连接正在积极地保持对数据的“锁定”(例如,这可能会阻止 auto-vacuum 正常工作)。

您显示的 pg_stat_activity 的结果并不表明有任何问题。

如您所见,问题是提交的事务,它们留在连接池中并阻止它

不,他们不会“阻止它”(至少你没有表现出任何迹象)。池只是让它们保持打开状态——这就是连接池的作用。

打开与 DBMS 的连接是一项非常昂贵的操作,因此最好将它们保持打开以供重复使用。

如果您想减少打开连接的数量(无论出于何种原因),那么您需要配置您的连接池来这样做(例如通过降低“空闲”超时)。您应该向我们展示您的连接池的配置,以确定一切是否正常。

于 2013-02-28T12:41:36.467 回答