2009-12-11 99 views
8

在我的应用程序中,Spring管理连接池以访问数据库。 Hibernate使用这些连接进行查询。乍一看,我对池没有任何问题:它对并发客户端和只有一个连接的池正常工作。我可以执行很多查询,所以我认为我(或Spring)不会保留打开的连接。连接在闲置之后挂起

我的问题出现一段时间后不活动(有时30分钟,有时超过2小时)。然后,当Hibernate进行一些搜索时,它会持续太久。 Log4j级别设置追查,我得到这个日志:

... 
18:27:01 DEBUG nsactionSynchronizationManager - Retrieved value [[email protected]] for key [[email protected]] bound to thread [http-8080-Processor24] 
18:27:01 DEBUG HibernateTransactionManager  - Found thread-bound Session [[email protected]] for Hibernate transaction 
18:27:01 DEBUG HibernateTransactionManager  - Using transaction object [org.springframework.orm.hi[email protected]1b2ffee] 
18:27:01 DEBUG HibernateTransactionManager  - Creating new transaction with name [com.acjoventut.service.GenericManager.findByExample]: PROPAGATION_REQUIRED,ISOLATION_DEFAULT 
18:27:01 DEBUG HibernateTransactionManager  - Preparing JDBC Connection of Hibernate Session [[email protected]] 
18:27:01 TRACE SessionImpl      - setting flush mode to: AUTO 
18:27:01 DEBUG JDBCTransaction     - begin 
18:27:01 DEBUG ConnectionManager    - opening JDBC connection 

这被冷冻约2 - 10分钟。但接着继续:

18:30:11 DEBUG JDBCTransaction     - current autocommit status: true 
18:30:11 DEBUG JDBCTransaction     - disabling autocommit 
18:30:11 TRACE JDBCContext      - after transaction begin 
18:30:11 DEBUG HibernateTransactionManager  - Exposing Hibernate transaction as JDBC transaction [jdbc:oracle:thin:@212.31.39.50:30998:orcl, UserName=DEVELOP, Oracle JDBC driver] 
18:30:11 DEBUG nsactionSynchronizationManager - Bound value [[email protected]] for key [[email protected]] to thread [http-8080-Processor24] 
18:30:11 DEBUG nsactionSynchronizationManager - Initializing transaction synchronization 
... 

之后,它的工作没有问题,直到另一个不活动的时期。恕我直言,它似乎像连接池返回一个无效/关闭连接,当Hibernate意识到这一点时,要求另一个连接池。

我不知道我该如何解决这个问题,或者我可以用它来分隔它。任何帮助实现这一点将不胜感激。

谢谢。

编辑:嗯,它最终是由于防火墙的规则。数据库检测到连接丢失,但池(dbcp或c3p0)不是。所以,它试图查询数据库没有成功。对我来说仍然很奇怪的是,超时时间非常多变。也许这个规则特别奇怪,或者防火墙无法正常工作。无论如何,我无法访问该机器,我只能等待解释。 :(

+0

你是如何确定这是否是防火墙的问题?我遇到了一个类似的问题,其中dbcp无限期地挂在我的Spring Batch事务上,并且永远不会返回 – YogendraJ 2016-05-20 05:06:31

回答

7

我以前有过这样的问题,当数据库是在一个单独的盒子,并且有一个之间的防火墙设置以超时闲置连接

在某些环境防火墙会阻止连接,导致JDBC端无法检测到,并尝试使用它会导致无限期的阻塞。

在我的情况下,它是一个自定义连接池,它在从池中返回它之前向连接发送测试查询。我将此测试查询配置为有超时(使用Statement.setQueryTimeout),以便它不会无限期地阻塞。

+0

我不确定为什么你会使用自定义池来只发送测试查询。一个体面的连接池和/或容器管理的数据源已经可以做到这一点。例如DBCP和Tomcat JNDI。请参阅每个关键字'validationQuery'下的配置文档。 – BalusC 2009-12-11 17:28:20

+0

这是一个很久以前的项目,它使用了一个定制的连接池,并且在代码段中确实与DBCP中的validationQuery做了类似的事情。 – Joe 2009-12-11 17:54:03

+0

你是对的。看来这个问题是一些防火墙排除我的控制。我认为最好的解决方案是改变防火墙行为。谢谢。 – sinuhepop 2009-12-29 14:18:37

1

检查池实现的配置。通常情况下,它的Apache DBCP具有a timeout为每个连接后,它会关闭它。

在你的代码,你不应该保持周围连接。获取一个,使用它,立即关闭池将确保这不会花费太多

+0

Spring管理我的连接,所以我不是那个必须明确调用Connection.close()的人。我是吗?正如你所说,我正在使用org.apache.commons.dbcp.BasicDataSource,并使用destroy-method =“close”。我会研究它。 – sinuhepop 2009-12-11 16:07:36

+1

还有其他两个问题的根源:您和数据库服务器之间可能存在防火墙(但空闲TCP连接上的2h超时有点短)。或者您的数据库配置为在一段时间后关闭空闲连接。查看DBCP的其他配置选项来检查死连接并定期ping数据库以保持管道打开。 – 2009-12-12 12:39:02

+0

至于关闭:不,你不应该关闭它,但你应该结束事务(这将使Spring看到连接可以返回到池中)。 – 2009-12-12 12:39:48

1

解决空闲超时问题的一种方法是拥有双连接池,一个处于活动状态,另一个处于待机状态(尚未创建连接)。有一个触发时间比FIREWALL_IDLE_TIMEOUT小得多的定时器,并在连接池之间切换。我试过这个和它的工作。

1

你必须添加在您的数据源的一些参数:

更重要补充testOnBorrow和validationQuery

1

我们解决的问题有类似症状也横空出世由防火墙引起。

我们可以通过改变其阻止去闲置和防火墙关闭连接的连接testWhileIdle连接池属性来解决此问题。见Apache commons dbcp BasicDataSource。下面是从配置文件,persistentce-context.xml中的使出的是解决了这一问题:

<property name="testWhileIdle"> 
    <value>true</value> 
</property> 
<property name="minEvictableIdleTimeMillis"> 
    <value>600000</value> 
</property> 
<property name="timeBetweenEvictionRunsMillis"> 
    <value>600000</value> 
</property> 

最有可能的,我们只需要添加testWhileIdle(默认为false),但添加了其他两个属性的好办法。

在我们的案例中,这里是我们看到的一些日志。注意在这个调试日志中,在连接可能被使用之前,需要16分钟才能打开连接,这是导致一切都挂起的原因。没有任何错误导致难以追查。

09-06-13 @ 16:36:34 [DEBUG] HibernateTransactionManager - Preparing JDBC Connection of Hibernate Session [[email protected]] 
09-06-13 @ 16:36:34 [DEBUG] ConnectionManager - opening JDBC connection 
09-06-13 @ 16:52:00 [DEBUG] DataSourceUtils - Setting JDBC Connection 
09-06-13 @ 16:52:00 [DEBUG] JDBCTransaction - begin 
09-06-13 @ 16:52:00 [DEBUG] JDBCTransaction - current autocommit status: true