我用Hibernate 3和postgres开发了一个web应用程序。问题是,执行和提交的每个查询都不会释放池中的连接(limit = 100)。我做了一些查询DB后的一个动作(SELECT, INSERT等…),我得到了结果:
查询:SELECT pid, query, state FROM pg_stat_activity;
<>之前5436年,"选择…";"idle"<-这是可以的6776年,"选择……"活跃"<-没关系5324年,"提交";"空闲"6840年,"提交";"空闲"6276年,"提交";"空闲"4804年,"提交";"空闲"5812年,"提交";"空闲"2608年,"提交";"空闲"2576年,"提交";"空闲"3896年,"提交";"空闲"4660年,"提交";"空闲"692年,"提交";"空闲"之前正如您所看到的,问题是提交的事务,它们留在连接池中并阻塞它。接下来的动作导致它不断增长,当池过量时,它无法连接到DB。我知道有一种方法可以手动删除它们(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" />
idle
不是问题。这只是一种开放的联系,没有任何作用。
idle in transaction
将是一个问题,因为这些连接正在积极地保持对数据的"锁定"(例如,可能会阻止自动真空正常工作)。
您所显示的pg_stat_activity的结果没有显示任何问题。
正如你所看到的问题是提交的事务,它们留在连接池中并阻塞它
不,他们没有"阻止它"(至少你没有表现出任何迹象)。连接池只是使它们保持打开状态——这就是连接池所做的。
打开到DBMS的连接是一个相当昂贵的操作,因此最好保持它们打开以供重用。
如果你想减少打开连接的数量(无论出于什么原因),那么你需要配置你的连接池来这样做(例如,通过降低"空闲"超时)。您应该向我们展示连接池的配置,以便确定是否一切正常。