对于连接池解析 MySql超过8小时连接报错的解决方案

一、复现:

项目运行一段时间未访问数据库(不进行任何操作),再次访问时会出现第一次访问报错,再次访问正常的现象。

二、分析原因:

Mysql服务器默认的“wait_timeout”是8小时,也就是说一个connection空闲超过8个小时,Mysql将自动断开该connection。connections如果空闲超过8小时,

Mysql将其断开,而数据源(DBCP或C3P0)并不知道该connection已经失效,如果这时有Client请求connection,连接池将该失效的Connection提供给Client,将会造成异常。

org.apache.jasper.JasperException: javax.servlet.ServletException: 
javax.servlet.jsp.JspException: : Communications link failure Last packet sent to the server was 1 ms ago. 
org.apache.jasper.servlet.JspServletWrapper.handleJspException
(JspServletWrapper.java:522) org.apache.jasper.servlet.JspServletWrapper.service(JspServletWrapper.java:398) 
org.apache.jasper.servlet.JspServlet.serviceJspFile(JspServlet.java:342)
org.apache.jasper.servlet.JspServlet.service(JspServlet.java:267) 
javax.servlet.http.HttpServlet.service(HttpServlet.java:717)

三、DBCP解决方案

1、DBCP连接池说明:driverClassName url username password上面四个分别是驱动,连接字符串,用户名和密码

    maxActive连接池支持的最大连接数

    maxIdle连接池中最多可空闲maxIdle个连接

    minIdle连接池中最少空闲maxIdle个连接

   initialSize 初始化连接数目

    maxWait连接池中连接用完时,新的请求等待时间,毫秒

   timeBetweenEvictionRunsMillis和minEvictableIdleTimeMillis一起使用,每timeBetweenEvictionRunsMillis毫秒秒检查一次连接池中空闲的连接,把空闲时间超过minEvictableIdleTimeMillis毫秒的连接断开,直到连接池中的连接数到minIdle为止主要把这两个参数加上就好。

   minEvictableIdleTimeMillis 连接池中连接可空闲的时间,

   毫秒removeAbandoned true,false,是否清理

   removeAbandonedTimeout秒没有使用的活动连接,清理后并没有放回连接池

   removeAbandonedTimeout 活动连接的最大空闲时间

   logAbandoned true,false,连接池收回空闲的活动连接时是否打印消息

   minEvictableIdleTimeMillis,removeAbandonedTimeout这两个参数针对的连接对象不样

   minEvictableIdleTimeMillis针对连接池中的连接 对象,

   removeAbandonedTimeout针对未被close的活动连接

原因是DBCP保持连接的超时时间比MySQL连接超时时间长。mysql配置中的wait_timeout值一定要大于等于连接池的idle_timeout值,否则mysql会在wait_timeout的时间后关闭连接,然而连接池还认为该连接可用,这样就会产生异常。

2、

那样,在DBCP中我们需要处理好以下问题:
a、对每个连接进行检查
b、对一次操作数据库超过多少时间的连接进行移除
c、每隔多少时间检测一次连接
d、一个连接在连接多少时间后,就必须删除

配置如下:

<bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource">
 <property name="driverClassName" value="com.mysql.jdbc.Driver" />
 <property name="url" value="jdbc:mysql://192.168.40.10:3336/XXX" />
 <property name="username" value="" />
 <property name="password" value="" />
 <property name="maxWait" value="20000"></property>
 <property name="validationQuery" value="SELECT 1"></property>
 <property name="testWhileIdle" value="true"></property>
 <property name="testOnBorrow" value="true"></property>
 <property name="timeBetweenEvictionRunsMillis" value="3600000"></property>
 <property name="numTestsPerEvictionRun" value="50"></property>
 <property name="minEvictableIdleTimeMillis" value="120000"></property>
 <property name="removeAbandoned" value="true"/>
 <property name="removeAbandonedTimeout" value="6000000"/>
</bean>
其中 testOnBorrow validationQuery 很重要。

testOnBorrow的意思是从数据库连接池中取得连接时,对其的有效性进行检查。

validationQuery 是用来检查的SQL语句,“select 1”执行较快,是一个不错的检测语句。


四、连接池为C3P0解决方案

1. 增加 MySQL 的 wait_timeout 属性的值 

a、修改mysql安装目录下的配置文件 my.ini文件(如果没有此文件,复制“my-default.ini”文件,生成“复件 my-default.ini”文件。将“复件 my-default.ini”文件重命名成“my.ini” ),在文件中设置:

    wait_timeout=31536000  
    interactive_timeout=31536000  
这两个参数的默认值是 8小时(60*60* 8=28800)。

wait_timeout的最大值只允许2147483 (24天左右)

。。。。。。


b、mysql命令对这两个属性进行修改

mysql> show variables like '%timeout%';



2.减少连接池内连接的生存周期

减少连接池内连接的生存周期,使之小于上一项中所设置的 wait_timeout 的值。

修改 c3p0 的配置文件,设置:

# How long to keep unused connections around(in seconds)
# Note: MySQL times out idle connections after 8 hours(28,800 seconds)
# so ensure this value is below MySQL idle timeout
cpool.maxIdleTime=25200

    <bean id="dataSource"  
         class="com.mchange.v2.c3p0.ComboPooledDataSource">  
        <property name="maxIdleTime" value="${cpool.maxIdleTime}" />  
        <!-- other properties -->  
    </bean>  

3. 定期使用连接池内的连接,使得它们不会因为闲置超时而被 MySQL 断开。

修改 c3p0 的配置文件,设置:

# Prevent MySQL raise exception after a long idle time
cpool.preferredTestQuery='SELECT 1'
cpool.idleConnectionTestPeriod=18000
cpool.testConnectionOnCheckout=true

修改 Spring 的配置文件:

<bean id="dataSource"  
       class="com.mchange.v2.c3p0.ComboPooledDataSource">  
    <property name="preferredTestQuery"  
           value="${cpool.preferredTestQuery}" />  
    <property name="idleConnectionTestPeriod"  
           value="${cpool.idleConnectionTestPeriod}" />  
    <property name="testConnectionOnCheckout"  
           value="${cpool.testConnectionOnCheckout}" />  
    <!-- other properties -->  
</bean> 



  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值