2014-10-17 73 views
2

我有我的Spring Hibernate Web應用程序運行在MySQL上給我帶來麻煩。JDBC連接超時不能重新連接

我已經搜索了四周,嘗試了不同的配置,在這個網站上閱讀了很多主題,但它仍然會彈出它的笑臉。

錯誤消息是: 原因:com.mysql.jdbc.exceptions.jdbc4.CommunicationsException:從服務器成功接收的最後一個數據包是63,313,144毫秒前。成功發送到服務器的最後一個數據包是63,313,144毫秒前。比服務器配置的'wait_timeout'值長。在應用程序中使用之前,應考慮過期和/或測試連接有效性,增加服務器配置的客戶端超時值,或者使用Connector/J連接屬性'autoReconnect = true'來避免此問題。

Caused by: com.mysql.jdbc.exceptions.jdbc4.CommunicationsException: The last packet successfully received from the server was 63,313,144 milliseconds ago. The last packet sent successfully to the server was 63,313,144 milliseconds ago. is longer than the server configured value of 'wait_timeout'. You should consider either expiring and/or testing connection validity before use in your application, increasing the server configured values for client timeouts, or using the Connector/J connection property 'autoReconnect=true' to avoid this problem. 
    at sun.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method) 
    at sun.reflect.NativeConstructorAccessorImpl.newInstance(NativeConstructorAccessorImpl.java:57) 
    at sun.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:45) 
    at java.lang.reflect.Constructor.newInstance(Constructor.java:526) 
    at com.mysql.jdbc.Util.handleNewInstance(Util.java:408) 
    at com.mysql.jdbc.SQLError.createCommunicationsException(SQLError.java:1137) 
    at com.mysql.jdbc.MysqlIO.send(MysqlIO.java:3965) 
    at com.mysql.jdbc.MysqlIO.sendCommand(MysqlIO.java:2578) 
    at com.mysql.jdbc.MysqlIO.sqlQueryDirect(MysqlIO.java:2758) 
    at com.mysql.jdbc.ConnectionImpl.execSQL(ConnectionImpl.java:2820) 
    at com.mysql.jdbc.ConnectionImpl.setAutoCommit(ConnectionImpl.java:5359) 
    at net.sf.log4jdbc.ConnectionSpy.setAutoCommit(ConnectionSpy.java:764) 
    at com.mchange.v2.c3p0.impl.NewProxyConnection.setAutoCommit(NewProxyConnection.java:912) 
    at org.hibernate.engine.transaction.internal.jdbc.JdbcTransaction.doBegin(JdbcTransaction.java:72) 
    at org.hibernate.engine.transaction.spi.AbstractTransactionImpl.begin(AbstractTransactionImpl.java:162) 
    at org.hibernate.internal.SessionImpl.beginTransaction(SessionImpl.java:1435) 
    at org.hibernate.jpa.internal.TransactionImpl.begin(TransactionImpl.java:61) 
    at org.springframework.orm.jpa.vendor.HibernateJpaDialect.beginTransaction(HibernateJpaDialect.java:159) 
    at org.springframework.orm.jpa.JpaTransactionManager.doBegin(JpaTransactionManager.java:380) 
    ... 46 more 
Caused by: java.net.SocketException: Broken pipe 
    at java.net.SocketOutputStream.socketWrite0(Native Method) 
    at java.net.SocketOutputStream.socketWrite(SocketOutputStream.java:113) 
    at java.net.SocketOutputStream.write(SocketOutputStream.java:159) 
    at java.io.BufferedOutputStream.flushBuffer(BufferedOutputStream.java:82) 
    at java.io.BufferedOutputStream.flush(BufferedOutputStream.java:140) 
    at com.mysql.jdbc.MysqlIO.send(MysqlIO.java:3946) 
    ... 58 more 

MySQL的WAIT_TIMEOUT值是28800

我的數據源,C3P0和Hibernate的配置是:

@Bean 
public DataSource dataSource() throws PropertyVetoException { 
    ComboPooledDataSource dataSource = new ComboPooledDataSource(); 
    dataSource.setDriverClass(databaseProperties.getHibernateDriverClassName()); 
    dataSource.setJdbcUrl(databaseProperties.getDataSourceUrl()); 
    dataSource.setUser(databaseProperties.getDataSourceUsername()); 
    dataSource.setPassword(databaseProperties.getDataSourcePassword()); 
    dataSource.setAcquireIncrement(5); 
    dataSource.setMaxStatementsPerConnection(20); 
    dataSource.setMaxStatements(100); 
    dataSource.setMinPoolSize(2); 
    dataSource.setMaxPoolSize(5); 
    return dataSource; 
} 

@Bean 
public LocalContainerEntityManagerFactoryBean entityManagerFactory() throws PropertyVetoException { 
    HibernateJpaVendorAdapter jpaVendorAdapter = new HibernateJpaVendorAdapter(); 
    jpaVendorAdapter.setDatabasePlatform(databaseProperties.getHibernateDialect()); 
    jpaVendorAdapter.setShowSql(true); 
    jpaVendorAdapter.setGenerateDdl(false); 

    Map<String, String> jpaPropertiesMap = new HashMap<String, String>(); 
    jpaPropertiesMap.put("hibernate.dialect", databaseProperties.getHibernateDialect()); 
    jpaPropertiesMap.put("hibernate.show_sql", "true"); 
    jpaPropertiesMap.put("hibernate.format_sql", "true"); 
    jpaPropertiesMap.put("hibernate.hbm2ddl.auto", databaseProperties.getHibernateHbm2ddlAuto()); 
    jpaPropertiesMap.put("hibernate.transaction.factory_class", "org.hibernate.transaction.JDBCTransactionFactory"); 
    jpaPropertiesMap.put("hibernate.ejb.naming_strategy", "org.hibernate.cfg.ImprovedNamingStrategy"); 
    jpaPropertiesMap.put("hibernate.c3p0.min_size", "5"); 
    jpaPropertiesMap.put("hibernate.c3p0.max_size", "20"); 
    jpaPropertiesMap.put("hibernate.c3p0.timeout", "1000"); 
    jpaPropertiesMap.put("c3p0.maxConnectionAge", "7200"); 
    jpaPropertiesMap.put("c3p0.maxIdleTime", "7200"); 
    jpaPropertiesMap.put("c3p0.unreturnedConnectionTimeout", "60"); 
    jpaPropertiesMap.put("c3p0.debugUnreturnedConnectionStackTraces", "true"); 
    jpaPropertiesMap.put("hibernate.c3p0.max_statements", "50"); 
    // Prevent JPA from converting the dates to the UTC time zone 
    jpaPropertiesMap.put("jadira.usertype.autoRegisterUserTypes", "true"); 
    jpaPropertiesMap.put("jadira.usertype.databaseZone", "jvm"); 
    jpaPropertiesMap.put("jadira.usertype.javaZone", "jvm"); 

    LocalContainerEntityManagerFactoryBean factoryBean = new LocalContainerEntityManagerFactoryBean(); 
    factoryBean.setJpaVendorAdapter(jpaVendorAdapter); 
    factoryBean.setPackagesToScan("com.nsn.nitro.project.data.jpa.domain"); 
    factoryBean.setJpaPropertyMap(jpaPropertiesMap); 
    String[] mappingsResources = new String[] {"custom/typedef.hbm.xml"};   
    factoryBean.setMappingResources(mappingsResources); 
    factoryBean.setDataSource(dataSource()); 
    return factoryBean; 
} 

錯誤發生時,第二天早上我回來的Web應用程序和它整晚都沒有被訪問過。

我知道MySQL的wait_timeout是MySQL在關閉之前等待連接再次使用的秒數。

這意味着我的Web應用程序試圖使用已過期並已在MySQL端關閉的連接,而我的Web應用程序仍然認爲它是有效的連接。

我想我應該讓我的Web應用程序在MySQL之前超時連接。這樣,Web應用程序就不會重用任何已經超時並且在MySQL端關閉的連接,因爲連接在Web應用程序端已經超時。

感覺就像我所有的c3p0配置對超時未使用連接的效果都沒有起到作用。

我用下面的堆棧:

MySQL mysql-5.6.14 
mysql-connector-java 5.1.32 
Spring 4.1.0.RELEASE 
spring-data-jpa 1.6.2.RELEASE 
Hibernate 4.3.6.Final 
hibernate-jpa-2.1-api 1.0.0.Final 
C3P0 0.9.2.1 

什麼我在我的配置做錯了什麼?

或者我應該明確關閉連接?

下面是我如何設置倉庫:

public interface LanguageRepository extends GenericRepository<Language, Long> { 
} 

@Repository 
@Transactional 
public class GenericRepositoryImpl<T, ID extends Serializable> extends SimpleJpaRepository<T, ID> implements GenericRepository<T, ID> { 

    private EntityManager entityManager; 

    public GenericRepositoryImpl(JpaEntityInformation<T, ID> entityMetadata, EntityManager entityManager) { 
     super(entityMetadata, entityManager); 

     this.entityManager = entityManager; 
    } 

    public GenericRepositoryImpl(Class<T> domainClass, EntityManager entityManager) { 
     super(domainClass, entityManager); 

     this.entityManager = entityManager; 
    } 

    public EntityManager getEntityManager() { 
     return entityManager; 
    } 

    @Override 
    @Transactional 
    public T deleteById(ID id) throws EntityNotFoundException { 
     T entity = findOne(id); 
     if (entity != null) { 
      delete(entity); 
     } else { 
      throw new EntityNotFoundException("The entity could not be found and was not deleted"); 
     } 
     return entity; 
    } 

} 

public class GenericRepositoryFactoryBean<R extends JpaRepository<T, I>, T, I extends Serializable> extends JpaRepositoryFactoryBean<R, T, I> { 

    protected RepositoryFactorySupport createRepositoryFactory(EntityManager entityManager) { 
     return new BaseRepositoryFactory<T, I>(entityManager); 
    } 

    protected static class BaseRepositoryFactory<T, I extends Serializable> extends JpaRepositoryFactory { 

     private EntityManager entityManager; 

     public BaseRepositoryFactory(EntityManager entityManager) { 
      super(entityManager); 

      this.entityManager = entityManager; 
     } 

     @Override 
     protected Object getTargetRepository(RepositoryMetadata metadata) { 
      return new GenericRepositoryImpl<T, I>((JpaEntityInformation<T, I>) getEntityInformation(metadata.getDomainType()), entityManager); 
     } 

     @Override 
     protected Class<?> getRepositoryBaseClass(RepositoryMetadata metadata) { 
      return GenericRepositoryImpl.class; 
     } 
    } 

} 

@NoRepositoryBean 
public interface GenericRepository<T, ID extends Serializable> extends JpaRepository<T, ID> { 

    public EntityManager getEntityManager(); 

    public T deleteById(ID id) throws EntityNotFoundException; 

} 

我看不到正在執行任何close()方法,也稱爲在那裏。我的代碼中缺少一些東西?

編輯:增加了C3P0的日誌記錄。下面是輸出:

2014-10-17 14:29:00,464 INFO [AbstractPoolBackedDataSource] Initializing c3p0 pool... com.mchange. 
v2.c3p0.ComboPooledDataSource [ acquireIncrement -> 5, acquireRetryAttempts -> 30, acquireRetryDelay 
-> 1000, autoCommitOnClose -> false, automaticTestTable -> null, breakAfterAcquireFailure -> false, 
checkoutTimeout -> 0, connectionCustomizerClassName -> null, connectionTesterClassName -> com.mchan 
ge.v2.c3p0.impl.DefaultConnectionTester, dataSourceName -> agvw3s958cggbnis1syx|1acb901, debugUnretu 
rnedConnectionStackTraces -> false, description -> null, driverClass -> net.sf.log4jdbc.DriverSpy, f 
actoryClassLocation -> null, forceIgnoreUnresolvedTransactions -> false, identityToken -> agvw3s958c 
ggbnis1syx|1acb901, idleConnectionTestPeriod -> 0, initialPoolSize -> 3, jdbcUrl -> jdbc:log4jdbc:my 
sql://127.0.0.1:3306/nitroproject, maxAdministrativeTaskTime -> 0, maxConnectionAge -> 0, maxIdleTim 
e -> 0, maxIdleTimeExcessConnections -> 0, maxPoolSize -> 5, maxStatements -> 100, maxStatementsPerC 
onnection -> 20, minPoolSize -> 2, numHelperThreads -> 3, preferredTestQuery -> null, properties -> 
{user=******, password=******}, propertyCycle -> 0, statementCacheNumDeferredCloseThreads -> 0, test 
ConnectionOnCheckin -> false, testConnectionOnCheckout -> false, unreturnedConnectionTimeout -> 0, u 
serOverrides -> {}, usesTraditionalReflectiveProxies -> false ] 
2014-10-17 14:29:00,479 DEBUG [BasicResourcePool] incremented pending_acquires: 1 
2014-10-17 14:29:00,480 DEBUG [BasicResourcePool] Starting acquisition series. Incremented pending_ 
acquires [1], attempts_remaining: 30 
2014-10-17 14:29:00,480 DEBUG [ThreadPoolAsynchronousRunner] com.mchange.v2.async.ThreadPoolAsynchr 
[email protected]: Adding task to queue -- com.mchange.v2.resourcepool.BasicResourcePool$Scattered 
[email protected] 
2014-10-17 14:29:00,481 DEBUG [BasicResourcePool] incremented pending_acquires: 2 
2014-10-17 14:29:00,481 DEBUG [BasicResourcePool] Starting acquisition series. Incremented pending_ 
acquires [2], attempts_remaining: 30 
2014-10-17 14:29:00,482 DEBUG [ThreadPoolAsynchronousRunner] com.mchange.v2.async.ThreadPoolAsynchr 
[email protected]: Adding task to queue -- com.mchange.v2.resourcepool.BasicResourcePool$Scattered 
[email protected] 
2014-10-17 14:29:00,482 DEBUG [BasicResourcePool] incremented pending_acquires: 3 
2014-10-17 14:29:00,483 DEBUG [BasicResourcePool] Starting acquisition series. Incremented pending_ 
acquires [3], attempts_remaining: 30 
2014-10-17 14:29:00,483 DEBUG [ThreadPoolAsynchronousRunner] com.mchange.v2.async.ThreadPoolAsynchr 
[email protected]: Adding task to queue -- com.mchange.v2.resourcepool.BasicResourcePool$Scattered 
[email protected] 
2014-10-17 14:29:00,511 DEBUG [GooGooStatementCache] checkinAll(): com.mchange.v2.c3p0.stmt.DoubleMaxStatementCache stats -- total size: 0; checked out: 0; num connections: 0; num keys: 0 
2014-10-17 14:29:00,523 DEBUG [C3P0PooledConnectionPool] com.mchange.v2.c3p0.imp[email protected]e38aca.acquireResource() returning. 
2014-10-17 14:29:00,523 DEBUG [BasicResourcePool] trace [email protected] [managed: 1, unused: 1, excluded: 0] 
2014-10-17 14:29:00,523 DEBUG [BasicResourcePool] decremented pending_acquires: 2 
2014-10-17 14:29:00,523 DEBUG [BasicResourcePool] Acquisition series terminated successfully. Decremented pending_acquires [2], attempts_remaining: 30 
2014-10-17 14:29:00,521 DEBUG [BasicResourcePool] [email protected] config: [start -> 3; min -> 2; max -> 5; inc -> 5; num_acq_attempts -> 30; acq_attempt_delay -> 1000; check_idle_resources_delay -> 0; mox_resource_age -> 0; max_idle_time -> 0; excess_max_idle_time -> 0; destroy_unreturned_resc_time -> 0; expiration_enforcement_delay -> 0; break_on_acquisition_failure -> false; debug_store_checkout_exceptions -> false] 
2014-10-17 14:29:00,523 DEBUG [C3P0PooledConnectionPoolManager] Created new pool for auth, username (masked): 'ni******'. 
2014-10-17 14:29:00,523 DEBUG [BasicResourcePool] trace [email protected] [managed: 1, unused: 0, excluded: 0] (e.g. com.mchange.v2.c3p0.impl[email protected]) 
2014-10-17 14:29:00,524 DEBUG [GooGooStatementCache] checkinAll(): com.mchange.v2.c3p0.stmt.DoubleMaxStatementCache stats -- total size: 0; checked out: 0; num connections: 0; num keys: 0 
2014-10-17 14:29:00,525 DEBUG [C3P0PooledConnectionPool] com.mchange.v2.c3p0.imp[email protected]e38aca.acquireResource() returning. 
2014-10-17 14:29:00,525 DEBUG [BasicResourcePool] trace [email protected] [managed: 2, unused: 1, excluded: 0] (e.g. [email protected]) 
2014-10-17 14:29:00,525 DEBUG [BasicResourcePool] decremented pending_acquires: 1 
2014-10-17 14:29:00,529 DEBUG [BasicResourcePool] Acquisition series terminated successfully. Decremented pending_acquires [1], attempts_remaining: 30 
2014-10-17 14:29:00,525 DEBUG [GooGooStatementCache] checkinAll(): com.mchange.v2.c3p0.stmt.DoubleMaxStatementCache stats -- total size: 0; checked out: 0; num connections: 0; num keys: 0 
2014-10-17 14:29:00,530 DEBUG [C3P0PooledConnectionPool] com.mchange.v2.c3p0.imp[email protected]e38aca.acquireResource() returning. 
2014-10-17 14:29:00,530 DEBUG [BasicResourcePool] trace [email protected] [managed: 3, unused: 2, excluded: 0] (e.g. [email protected]) 
2014-10-17 14:29:00,530 DEBUG [BasicResourcePool] decremented pending_acquires: 0 
2014-10-17 14:29:00,530 DEBUG [BasicResourcePool] Acquisition series terminated successfully. Decremented pending_acquires [0], attempts_remaining: 30 
2014-10-17 14:29:00,562 DEBUG [GooGooStatementCache] checkinAll(): com.mchange.v2.c3p0.stmt.DoubleMaxStatementCache stats -- total size: 0; checked out: 0; num connections: 0; num keys: 0 
2014-10-17 14:29:00,574 DEBUG [ThreadPoolAsynchronousRunner] [email protected]: Adding task to queue -- com.mchange.[email protected]1fec09e 
2014-10-17 14:29:00,574 DEBUG [GooGooStatementCache] checkinAll(): com.mchange.v2.c3p0.stmt.DoubleMaxStatementCache stats -- total size: 0; checked out: 0; num connections: 0; num keys: 0 
2014-10-17 14:29:00,575 DEBUG [BasicResourcePool] trace [email protected] [managed: 3, unused: 2, excluded: 0] (e.g. [email protected]) 
2014-10-17 14:29:00,575 DEBUG [NewProxyConnection] [email protected]: close() called more than once. 
2014-10-17 14:29:02,260 DEBUG [BasicResourcePool] trace [email protected] [managed: 3, unused: 2, excluded: 0] (e.g. [email protected]) 
2014-10-17 14:29:03,111 DEBUG [GooGooStatementCache] checkinAll(): com.mchange.v2.c3p0.stmt.DoubleMaxStatementCache stats -- total size: 0; checked out: 0; num connections: 0; num keys: 0 
2014-10-17 14:29:03,112 DEBUG [ThreadPoolAsynchronousRunner] [email protected]: Adding task to queue -- com.mchange.[email protected]146219b 
2014-10-17 14:29:03,112 DEBUG [GooGooStatementCache] checkinAll(): com.mchange.v2.c3p0.stmt.DoubleM 
axStatementCache stats -- total size: 0; checked out: 0; num connections: 0; num keys: 0 
2014-10-17 14:29:03,113 DEBUG [BasicResourcePool] trace com.mchange.v2.resourcepool.BasicResourcePo 
[email protected] [managed: 3, unused: 2, excluded: 0] (e.g. [email protected]) 
2014-10-17 14:29:03,262 DEBUG [DefaultListableBeanFactory] Returning cached instance of singleton bean 'org.springframework.transaction.config.internalTransactionAdvisor' 
2014-10-17 14:29:03,285 DEBUG [DefaultListableBeanFactory] Finished creating instance of bean 'entityManagerFactory' 

然後它循環輸出這樣的:

2014-10-17 14:34:10,399 DEBUG [ThreadPoolAsynchronousRunner] com.mchange.v2.async.Th[email protected] -- Running DeadlockDetector[Exiting. No pending tasks.] 
2014-10-17 14:34:10,825 DEBUG [ThreadPoolAsynchronousRunner] com[email protected]15e34e2 -- Running DeadlockDetector[Exiting. No pending tasks.] 
2014-10-17 14:34:10,825 DEBUG [ThreadPoolAsynchronousRunner] com[email protected]15e34e2 -- Running DeadlockDetector[Exiting. No pending tasks.] 
+1

你能證實c3p0具有你認爲它具有的配置嗎?在INFO的池初始化時,c3p0轉儲DataSource配置。你能找到幷包含該日誌條目嗎? – 2014-10-17 11:03:01

+0

我看不到任何由C3P0記錄的語句,所以我想我必須配置我的日誌記錄... – Stephane 2014-10-17 12:01:35

+0

我讀到,當數據源被注入時,如我的情況,hibernate.c3p0屬性被忽略...我需要罰款調整配置。 – Stephane 2014-10-17 12:18:15

回答

2

我想這個問題出現,因爲數據庫服務器殺死連接,而應用程序的連接池仍然有一個手柄它。通過在應用程序連接池上超時而不是在數據庫服務器端上,連接在應用程序連接池被數據庫服務器殺死之前被更新,從而避免了該問題。我的MySQL數據庫服務器的超時等待時間爲28800秒,而我的應用程序連接池C3P0的超時等待時間爲14400秒。從服務器到客戶端,超時等待鏈必須縮短,這是有道理的。