连接已关闭

时间:2016-03-30 16:43:52

标签: mysql grails spring-jdbc

我使用的是Grails 2.5.3和Tomcat7,在应用程序部署8小时后,我们的日志开始爆炸,连接已经关闭。一个很好的假设是MySql在默认等待时间为8小时后终止连接。

通过文档,我的池似乎已正确配置以保持空闲连接打开,但似乎并非如此。

我的连接池设置可能出现什么问题?

dataSource {
  pooled = true
  url = 'jdbc:mysql://******.**********.us-east-1.rds.amazonaws.com/*****'
  driverClassName = 'com.mysql.jdbc.Driver'
  username = '********'
  password = '******************'
  dialect = org.hibernate.dialect.MySQL5InnoDBDialect
  loggingSql = false
  properties {
    jmxEnabled = true
    initialSize = 5
    timeBetweenEvictionRunsMillis = 10000
    minEvictableIdleTimeMillis = 60000
    validationQuery = "SELECT 1"
    initSQL = "SELECT 1"
    validationQueryTimeout = 10
    testOnBorrow = true
    testWhileIdle = true
    testOnReturn = true
    testOnConnect = true
    removeAbandonedTimeout = 300
    maxActive=100 
    maxIdle=10 
    minIdle=1
    maxWait=30000
    maxAge=900000
    removeAbandoned="true"
    jdbcInterceptors="org.apache.tomcat.jdbc.pool.interceptor.StatementCache;"

  }
}

hibernate {
  cache.use_second_level_cache=true
  cache.use_query_cache=true
  cache.region.factory_class = 'org.hibernate.cache.ehcache.EhCacheRegionFactory'
}

,我已确认运行时的dataSource是(org.apache.tomcat.jdbc.pool.DataSource)的实例

更新1(未修复) 我们认为我们可能已经发现了这个问题!我们在http会话中存储了一个域类,在阅读了一些关于会话工厂如何工作的内容后,我们认为存储的http对象以某种方式绑定到了一个连接。当用户在8小时后访问域类形成http会话时,我们认为hibernate存储了对死连接的引用。它现在正在生产中,我们正在监控。

更新2(已修复) 我们终于找到了问题。删除removeAbandoned和removeAbandonedTimeout解决了我们所有的问题。我们并不完全确定为什么这会解决问题,因为我们的假设是存在这两个属性以确切地防止发生的事情。唯一的想法是我们的​​数据库更积极地管理废弃的连接。它已经超过4周而没有任何问题。

3 个答案:

答案 0 :(得分:2)

我们的网址通常看起来很相似:

url = "jdbc:mysql://localhost/db?useUnicode=yes&characterEncoding=UTF-8&autoReconnect=true"

如果您不想面对这样的问题,请查看编码参数。

答案 1 :(得分:2)

我遇到了一个完全不同的设置问题。处理真的不好玩。基本上它归结为:

  1. 在Java正在进行某种“其他”处理时,您的应用程序中的某个位置只是坐在一起。这是一种非常基本的复制方式:

    连接con =(从池获取连接); 睡觉(330秒); con.close();

    1. 代码没有对上面的数据库连接做任何事情,所以tomcat将其检测为已放弃并在300秒后将其返回池中。

    2. 您的应用程序流量很大,以至于相同的连接(在上面的代码中打开和放弃)在应用程序的其他位置以不同的代码部分打开。

    3. 原始代码命中330秒并关闭连接,或者新代码获取连接并完成并关闭它。此时有两个地方使用相同的连接,其中一个已关闭它。

    4. 使用相同连接的其他代码位置然后尝试使用或关闭相同的连接

    5. 连接已关闭。产生上述错误。

  2. 建议的修复路线: 使用logAbandoned =“true”设置来查找放弃连接的位置。

答案 2 :(得分:0)

(见问题更新2)

删除 removeAbandoned removeAbandonedTimeout 解决了我们所有的问题。有人可能想要提供更详细的答案,说明为什么会这样做,因为我们并不完全确定。