mat*_*tst 10 connection spring hibernate pooling c3p0
我正在使用c3p0作为我的连接池运行Spring/Hibernate连接到MySQL设置.由于某些奇怪的原因,当系统处于负载状态时(当然)它会耗尽连接.
在我们开始达到新的流量水平(超过一百个并发用户)之前,该网站非常稳定.此时DB会熔化(固定CPU).我的第一个动作是在应用程序中通过广泛的缓存和查询优化等来提高性能.
现在它将间歇性地耗尽连接.它似乎甚至不依赖于负载.更多准时,这让我觉得这是一个泄漏,但对于我的生活,我无法弄清楚它将来自何处.
WARN [2011-03-07 17:19:42,409] [TP-Processor38] (JDBCExceptionReporter.java:100) - SQL Error: 0, SQLState: null
ERROR [2011-03-07 17:19:42,409] [TP-Processor38] (JDBCExceptionReporter.java:101) - An attempt by a client to checkout a Connection has timed out.
ERROR [2011-03-07 17:19:42,410] [TP-Processor38] (HttpHeadFilter.java:46) - There was a problem passing thru filter:/is-this-guy-crazy-or-just-a-huge-dancing-with-the-stars-fan
org.springframework.web.util.NestedServletException: Request processing failed; nested exception is org.hibernate.exception.GenericJDBCException: could not execute query
at org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:659)
at org.springframework.web.servlet.FrameworkServlet.doGet(FrameworkServlet.java:552)
at javax.servlet.http.HttpServlet.service(HttpServlet.java:617)
at javax.servlet.http.HttpServlet.service(HttpServlet.java:717)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:290)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:206)
at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:343)
at org.springframework.security.web.access.intercept.FilterSecurityInterceptor.invoke(FilterSecurityInterceptor.java:109)
Caused by: java.sql.SQLException: An attempt by a client to checkout a Connection has timed out.
at com.mchange.v2.sql.SqlUtils.toSQLException(SqlUtils.java:106)
at com.mchange.v2.sql.SqlUtils.toSQLException(SqlUtils.java:65)
at com.mchange.v2.c3p0.impl.C3P0PooledConnectionPool.checkoutPooledConnection(C3P0PooledConnectionPool.java:527)
at com.mchange.v2.c3p0.impl.AbstractPoolBackedDataSource.getConnection(AbstractPoolBackedDataSource.java:128)
Run Code Online (Sandbox Code Playgroud)
这是我的配置:
<bean id="dataSource" class="org.springframework.jdbc.datasource.LazyConnectionDataSourceProxy">
<property name="targetDataSource" ref="rootDataSource" />
</bean>
<bean id="sessionFactory" class="org.springframework.orm.hibernate3.LocalSessionFactoryBean">
<property name="mappingLocations" value="classpath:hibernate-mapping.xml" />
<property name="hibernateProperties">
<props>
<prop key="hibernate.connection.provider_class">net.sf.hibernate.connection.C3P0ConnectionProvider</prop>
<prop key="hibernate.dialect">${hibernate.dialect}</prop>
<prop key="hibernate.show_sql">${hibernate.show_sql}</prop>
<prop key="hibernate.cache.use_second_level_cache">true</prop>
<prop key="hibernate.cache.use_query_cache">true</prop>
<prop key="hibernate.cache.generate_statistics">true</prop>
<prop key="hibernate.cache.provider_class">net.sf.ehcache.hibernate.EhCacheProvider</prop>
<prop key="hibernate.generate_statistics">${hibernate.generate_statistics}</prop>
<prop key="hibernate.connection.zeroDateTimeBehavior">convertToNull</prop>
<prop key="hibernate.bytecode.use_reflection_optimizer">${hibernate.bytecode.use_reflection_optimizer}</prop>
<!--<prop key="hibernate.hbm2ddl.auto">${hibernate.hbm2ddl.auto}</prop>-->
<prop key="hibernate.jdbc.batch_size">${hibernate.jdbc.batch_size}</prop>
<!--Actually, it seems the following property affects batch size (or explicit per relationship in the mapping)-->
<!--<prop key="hibernate.default_batch_fetch_size">${hibernate.jdbc.batch_size}</prop>-->
</props>
</property>
<property name="dataSource" ref="dataSource" />
</bean>
<bean id="rootDataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource">
<property name="driverClass" value="${jdbc.driver}" />
<property name="jdbcUrl" value="${jdbc.url}" />
<property name="user" value="${jdbc.username}" />
<property name="password" value="${jdbc.password}" />
<property name="initialPoolSize" value="20" />
<property name="maxPoolSize" value="200" />
<property name="checkoutTimeout" value="30000" />
<property name="maxStatements" value="180" />
<property name="minPoolSize">
<value>${hibernate.c3p0.minPoolSize}</value>
</property>
<property name="acquireRetryAttempts">
<value>${hibernate.c3p0.acquireRetryAttempts}</value>
</property>
<property name="acquireIncrement">
<value>${hibernate.c3p0.acquireIncrement}</value>
</property>
<property name="idleConnectionTestPeriod">
<value>${hibernate.c3p0.idleConnectionTestPeriod}</value>
</property>
<property name="maxIdleTime">
<value>${hibernate.c3p0.maxIdleTime}</value>
</property>
<property name="maxIdleTimeExcessConnections">
<value>${hibernate.c3p0.maxIdleTimeExcessConnections}</value>
</property>
<property name="maxConnectionAge">
<value>${hibernate.c3p0.maxConnectionAge}</value>
</property>
<property name="preferredTestQuery">
<value>${hibernate.c3p0.preferredTestQuery}</value>
</property>
<property name="testConnectionOnCheckin">
<value>${hibernate.c3p0.testConnectionOnCheckin}</value>
</property>
<property name="numHelperThreads">
<value>${hibernate.c3p0.numHelperThreads}</value>
</property>
<property name="unreturnedConnectionTimeout">
<value>${hibernate.c3p0.unreturnedConnectionTimeout}</value>
</property>
<property name="debugUnreturnedConnectionStackTraces">
<value>${hibernate.c3p0.debugUnreturnedConnectionStackTraces}</value>
</property>
<property name="automaticTestTable">
<value>${hibernate.c3p0.automaticTestTable}</value>
</property>
</bean>
hibernate.c3p0.acquireIncrement=5
hibernate.c3p0.minPoolSize=20
hibernate.c3p0.acquireRetryAttempts=30
hibernate.c3p0.idleConnectionTestPeriod=3600
hibernate.c3p0.maxIdleTime=7200
hibernate.c3p0.maxIdleTimeExcessConnections=1800
hibernate.c3p0.maxConnectionAge=14400
hibernate.c3p0.preferredTestQuery=select 1;
hibernate.c3p0.testConnectionOnCheckin=false
hibernate.c3p0.numHelperThreads=6
hibernate.c3p0.unreturnedConnectionTimeout=0
hibernate.c3p0.debugUnreturnedConnectionStackTraces=true
hibernate.c3p0.automaticTestTable=test_connection;
Run Code Online (Sandbox Code Playgroud)
我正在运行OpenSessionInViewInterceptor,它应该关闭连接:
<bean id="openSessionInViewInterceptor" class="org.springframework.orm.hibernate3.support.OpenSessionInViewInterceptor">
<property name="sessionFactory">
<ref bean="sessionFactory" />
</property>
<property name="flushModeName">
<value>FLUSH_AUTO</value>
</property>
</bean>
Run Code Online (Sandbox Code Playgroud)
我也在使用@Transactional的spring注释,因为我在非web前端代码中重用了我的服务.
这里实际上只有两个选项,它在完成后不会释放连接.或者它正在闲聊和数据库聊天,就像它试图穿上裤子一样.如果有人有任何想法我会感激thx
关注:最后我发现由于使用了OpenSessionInViewInterceptor,我正在泄漏连接.我将spring security作为过滤器运行,因此它将连接到DB并且永远不会关闭它们.修复是将OpenSessionInViewInterceptor移动到OpenSessionInViewFilter.
Ang*_*own 12
尝试启用日志记录并将c3p0.debugUnreturnedConnectionStackTraces属性设置为true.还设置c3p0.unreturnedConnectionTimeout为小于平均查询时间(1秒?)的内容.然后,任何花费超过超时的事情都会记录堆栈跟踪.这应该可以让你很快缩小范围.
如果堆栈跟踪没有模式,那可能就是您的池太小了.你说100个并发用户,但任何想法每秒有多少查询?如果它是每秒100次查询并且您有20个连接,那么每个sql执行需要花费不到200毫秒(20个连接=每秒挂钟时间的总工作秒数> 20次以进行100次查询).
@Transactional泄漏连接的可能性很小- 否则,您的站点将在前100个请求后停止工作.
但是还有另一个原因:
也许你已经为"死"连接设置了超时,有些查询需要更长的时间.这意味着您的池从池中删除了一个忙碌的连接"死",并从数据库中请求另一个 - 直到DB拔出插件.
要对此进行调试,请启用连接池的日志记录,以便查看何时请求新连接.
| 归档时间: |
|
| 查看次数: |
44261 次 |
| 最近记录: |