博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
解决Mysql连接8小时空闲失效问题
阅读量:3960 次
发布时间:2019-05-24

本文共 4017 字,大约阅读时间需要 13 分钟。

博主在之前的博文中发过一篇博客,是关于flink高性能写入mysql或者Oracle的问题,虽然写入的性能提高了,但是在接下来其他项目的开发过程中,遇到过连接connection失效的问题。

博主的使用场景是这样的:

博主的项目是做的实时推送的工程,每推送成功一条,就插入mysql一条数据,考虑到夜晚对用户推送,可能会对用户有打扰,所以在22~07不对用户进行推送,因此在这个空档期,mysql的连接是没有使用的,所以会报connection连接失效,至此,博主之前提到的高性能写入mysql的方案就行不通了,因为那样的方式是不能设置connection的失效时间及检测的,在c3p0不理想的情况下,此次博主采用了DBCP连接池。

使用到的maven

org.apache.commons
commons-dbcp2
2.5.0

本人使用的工具类如下

package com.chinaTelecom.mySqlUtiles;import org.apache.commons.dbcp2.BasicDataSource;import javax.sql.DataSource;import java.sql.Connection;import java.sql.PreparedStatement;import java.sql.ResultSet;import java.sql.SQLException;public class DBCPUtils {    //建立连接的驱动驱动名称    public static final String DRIVER_CLASS_NAME = "***";    //数据库链接数据哭的url    public static final String URL = "***";    //链接的数据库账号    public static final String USERNAME = "***";    //链接的数据库密码    public static final String PASSWORD = "***";    //初始化时链接池的数量    private static final int INITIAL_SIZE = 10;    //的到链接实例    private static BasicDataSource dataSource = new BasicDataSource();    //初始化链接参数    static{        dataSource.setDriverClassName(DRIVER_CLASS_NAME);        dataSource.setUrl(URL);        dataSource.setUsername(USERNAME);        dataSource.setPassword(PASSWORD);        dataSource.setInitialSize(INITIAL_SIZE);   //初始化连接:连接池启动时创建的初始化连接数量        dataSource.setMaxTotal(10);        dataSource.setMaxIdle(6);   //最大空闲连接:连接池中容许保持空闲状态的最大连接数量,超过的空闲连接将被释放,如果设置为负数表示不限制        dataSource.setMinIdle(4);   //最小空闲连接:连接池中容许保持空闲状态的最小连接数量,低于这个数量将创建新的连接,如果设置为0则不创建        dataSource.setMinEvictableIdleTimeMillis(1000 * 60 * 60 * 10);  //连接在池中保持空闲而不被空闲连接回收器线程(如果有)回收的最小时间值,单位毫秒        dataSource.setTestOnBorrow(true);  //是否在从池中取出连接前进行检验,如果检验失败,则从池中去除连接并尝试取出另一个.        dataSource.setTestOnCreate(true);  //指明对象在创建后是否需要验证是否有效,如果对象验证失败,则触发对象创建的租借尝试将失败。        dataSource.setTestWhileIdle(true);  //指明对象是否需要通过对象驱逐者进行校验(如果有的话),假如一个对象验证失败,则对象将被从池中释放。和timeBetweenEvictionRunsMillis配合使用。        dataSource.setTimeBetweenEvictionRunsMillis(100000); //在空闲连接回收器线程运行期间休眠的时间值,以毫秒为单位,即每100秒做一次idle连接的检测,检测语句为validationQuery。        dataSource.setValidationQuery("select 1"); //SQL查询,用来验证从连接池取出的连接,验证连接是否有效,查询必须是一个SQL SELECT并且必须返回至少一行记录。        dataSource.setNumTestsPerEvictionRun(10);  //每次空闲连接回收器线程运行时检查的连接数量    }    //提供获得数据源    public static DataSource getDateSource(){        return dataSource;    }    //提供获得链接    public static Connection getConnection() throws SQLException {        return dataSource.getConnection();    }	//测试connection是否正常    public static void main(String[] args) throws SQLException {        Connection connection = DBCPUtils.getConnection();        PreparedStatement ps = connection.prepareStatement("select * from phoneNum");        ResultSet rs = ps.executeQuery();        while (rs.next()){            String string = rs.getString(2);            System.out.println(string);        }    }}

参数解读

testOnBorrow=false 表示使用连接池中的连接时,不做检测,这个也是推荐配置,如果设置为true会影响数据库的性能。

testWhileIdle=true 指明连接是否被空闲连接回收器进行检验,如果检测失败,则连接将被从池中去除,和timeBetweenEvictionRunsMillis配合使用。

validationQuery=select 1 SQL查询,用来验证从连接池取出的连接,验证连接是否有效,查询必须是一个SQL SELECT并且必须返回至少一行记录。

timeBetweenEvictionRunsMillis=100000 在空闲连接回收器线程运行期间休眠的时间值,以毫秒为单位,即每100秒做一次idle连接的检测,检测语句为validationQuery。

minEvictableIdleTimeMillis=600000 连接在池中保持空闲而不被空闲连接回收器线程,即idle连接的保存时间为600秒(10分钟)

感觉没有问题,每100秒就会做idle线程的检测,应用的检测时间600秒也小于数据库设置的1800秒的时间,为什么还会有连接失效的异常?且报的连接失效时长越来越长。

分析

看dbcp源码看到还有一个参数numTestsPerEvictionRun ,在每次空闲连接回收器线程运行时检查的连接数量,这个参数配置了每100秒检测的idle线程的数量。这个参数我们没有配置,走的是默认值。

protected int numTestsPerEvictionRun = 3;

源码中配置的是3,就是默认每次只检测3个idle线程。

按照最坏的情况,最大的idle线程为800,每100秒执行3个idle线程的判断,判断完所有的idle线程的状态需要 (800/3) * 100秒=26666秒,而数据库的超时是1800秒,这意味着如果池子满了(或者池子中的连接数很多)的话,到所有的idle线程都检测完成,应用是很大概率会取到已经失效的连接的。最早的超时连接应该是在30分钟之后也就是数据库配置的1800秒

解决

网上大家的推荐配置是设置numTestsPerEvictionRun=maxIdle,这样一次检测就都可以把失效的idle都移出线程池,避免了一个高峰之后,连接池的连接已经失效的问题。

鉴于失效的连接会被慢慢的剔除,当时没有做修改配置的操作,之后会把numTestsPerEvictionRun参数配置成和maxIdle一样的值,可以避免这个问题的发生。

转载地址:http://zimzi.baihongyu.com/

你可能感兴趣的文章
java 注意事项[教学]
查看>>
MetaWeblogAPI测试
查看>>
软件配置管理概念-1,介绍
查看>>
软件配置管理概念-2,用户角色
查看>>
软件配置管理概念-3,CM系统的概念
查看>>
JSP/Servlet应用程序优化八法
查看>>
人生必修的181条佛理
查看>>
The Most Widely Used Java Libraries
查看>>
简单在单机使用apache-james(开源邮件服务器)
查看>>
lsof 快速起步
查看>>
使用ScribeFire方便地发布blog
查看>>
跨平台Java程序注意事项
查看>>
Python字符与数字的相互转换
查看>>
C 指针解读
查看>>
有关乱码的处理---中国程序员永远无法避免的话题
查看>>
JSP的运行内幕
查看>>
python超简单的web服务器
查看>>
代理模式、静态代理、动态代理、aop
查看>>
Struts1.x Spring2.x Hibernate3.x DWR2.x整合工具文档v1.00
查看>>
大型Web2.0站点构建技术初探
查看>>