2011-03-08 7 views
9

내 연결 풀로 c3p0을 사용하여 MySQL 설치에 연결하는 Spring/Hibernate를 실행 중입니다. 기묘한 이유로 시스템에 부하가 걸렸을 때 연결이 끊어집니다 (당연히).DB 연결이 끊어졌습니다!

사이트는 새로운 수준의 트래픽 (100 명 이상의 동시 사용자)을 치기 시작할 때까지 꽤 안정적이었습니다. 그 시점에서 DB는 녹아 내릴 것입니다 (CPU를 페그). 첫 번째 작업은 광범위한 캐싱 및 쿼리 최적화 등을 통해 성능을 향상시키는 응용 프로그램에서였습니다.

이제는 간헐적으로 연결이 끊어집니다. 부하에 의존하는 것조차 보이지 않습니다. 시간이 지남에 따라 그것이 누수라고 생각하게하지만, 내 인생에서 나는 그것이 어디서 오는 것인지 알 수 없습니다. 내가 연결을 종료해야 OpenSessionInViewInterceptor 실행하고

<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; 

: 여기

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) 

내 구성의 I 재사용하기 때문에 나는 또한 @Transactional의 스프링 주석을 사용하고

<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> 

을 내 비 웹 프론트 코드의 서비스.

여기에는 실제로 두 가지 옵션 만 있습니다. 완료되면 연결을 해제하지 않습니다. 또는 바지를 입으려는 것처럼 DB를보고 놀고 있습니다. 그것이 내가 OpenSessionInViewInterceptor을 사용하기 때문에 연결이 유출 된 밝혀 결국 : 사람이 어떤 아이디어를 가지고 경우에 나는 들으

FOLLOW UP 감사 할 것입니다. 나는 봄 보안을 필터로 실행하여 DB에 연결하고 절대 닫지 않았습니다. 해결 방법은 OpenSessionInViewInterceptor를 OpenSessionInViewFilter로 이동하는 것입니다.

답변

5

@Transactional이 연결을 유출하는 것은 거의 없습니다. 그렇지 않으면 사이트가 처음 100 번 요청한 후에 작동을 멈 춥니 다.

그러나 이런 일이 발생하는 또 다른 이유가있다 :

은 어쩌면 당신은 "죽은"연결 및 일부 쿼리는보다 오래 걸릴 수에 대한 제한 시간을 설정 한가. 즉, 수영장에서 바쁜 연결이 풀에서 "죽은"것으로 제거되고 DB에서 플러그를 뽑을 때까지 DB에서 다른 연결을 요청합니다.

디버깅하려면 연결 풀에 대한 로깅을 사용하도록 설정하여 새 연결을 요청할시기를 확인하십시오.

+0

이 내 maxConnectionAge이 문서에 따라 초 (하지 MS)에 14400로 설정 :

여기 문서를 참조하십시오. 아쉽게도 로깅을 켜십시오. 문제는 연결의 TON을 열거 나 닫음으로써 일어나는 일을 고립시키는 것이 어렵다는 것입니다. 특히 부하가 심하다. – matsientst

12

로깅을 사용하고 c3p0.debugUnreturnedConnectionStackTraces 속성을 true로 설정해보십시오. 또한 c3p0.unreturnedConnectionTimeout을 평균 쿼리 시간 (1 초?)보다 작은 값으로 설정하십시오. 그런 다음 시간 초과보다 오래 걸리면 스택 추적이 기록됩니다. 이것은 당신이 일을 꽤 빨리 좁힐 수있게합니다.

스택 추적에 패턴이 없으면 풀이 너무 작을 수 있습니다. 당신은 100 명의 동시 사용자를 말했지만, 초당 얼마나 많은 쿼리가 있을까요? 초당 100 개의 쿼리가 있고 20 개의 연결이있는 경우 각 SQL 실행은 200 밀리 초 (20 개의 연결 = 100 개의 쿼리를 수행하는 데 월 시계의 초당 총 작업 시간 20 초 미만)가 걸릴 필요가 있습니다.

+0

+1 작은 시간 초과를 사용하여 더 빨리 추적합니다. –

3

C3P0 (최대 절전 모드)에 대한 구성에 관계없이 MySQL 자체에 의해 제한이있을 수 있습니다.기본적으로 MySQL이 허용하는 최대 연결 수는 100입니다! 따라서 C3P0에 최대 200, 500 또는 1000 개의 연결을 풀링한다고해도이 방법을 사용할 수는 없습니다.

$ msql -u [user] -p 

를 입력 연결의 최대 수를 허용 얻을하려면 다음을 수행하십시오 : 사용하여 MySQL의 쉘을 열고 편집 (반환 수는 응용 프로그램에 대한 너무 낮

$ show variables where Variable_name='max_connections'; 

경우, 변경을 고려하여 my.cnf 파일, 일반적으로/etc/mysql /에 있습니다).

0

이 문제가 발생했습니다. 원인은/etc/hosts 항목이 수정 되었기 때문에 사용자에게 호스트에 대한 권한이 없다는 것입니다.

0

나는이 문제를했고 나는 재산 checkoutTimeout 사실 나는 연결하고 10 초 후 대기하는 스레드를 많이 가지고 더 높은 0보다

대신 값을 0으로 C3P0의를 설정하여 그것을 해결 너와 같은 에로스가 일어났다. 그 240 분으로 할 수 있도록 http://www.mchange.com/projects/c3p0/#checkoutTimeout

관련 문제