druid discard long time none received connection问题解析

最新项目中用的druid链接数据库遇到一个困扰好久的问题mysql

1 开始用的druid版本是1.1.22版本,因为业务需求,单个链接须要执行好久,理论上不须要用到自动回收,但为了安全,仍是加了自动回收,时间设置的2个小时。sql

问题来了,程序常常报The last packet successfully received from the server was XXXXX milliseconds ago.  The last packet sent successfully to the server was 0 mill
iseconds ago错误,网上搜索了下答案,有说配置项,改数据库事件设置,试过都没有解决,后续看到https://cloud.tencent.com/developer/article/1397508 分析,以为有必定道理,就开始后续之路数据库

2.druid包升级到1.2.2,原来的问题是没有了,新的问题出现了,discard long time none received connection,又继续网上搜索答案,出来的结果一塌糊涂,不少说版本回退到1.1.22,内心不禁的说wc,这...安全

有点扯,继续进行搜索测试,修改配置项validationQuery,修改testWhileIdle,修改...继续测试,问题依旧,又搜索到运行时添加druid.mysql.usePingMethod=false,可是没说怎样添加,没办法下载源码进行查看,导入源码后发现以下:ide

 if (valid && isMySql) { // unexcepted branch
                    long lastPacketReceivedTimeMs = MySqlUtils.getLastPacketReceivedTimeMs(conn);
                    if (lastPacketReceivedTimeMs > 0) {
                        long mysqlIdleMillis = currentTimeMillis - lastPacketReceivedTimeMs;
                        if (lastPacketReceivedTimeMs > 0 //
                                && mysqlIdleMillis >= timeBetweenEvictionRunsMillis) {
                            discardConnection(holder);
                            String errorMsg = "discard long time none received connection. "
                                    + ", jdbcUrl : " + jdbcUrl
                                    + ", version : " + VERSION.getVersionNumber()
                                    + ", lastPacketReceivedIdleMillis : " + mysqlIdleMillis;
                            LOG.warn(errorMsg);
                            return false;
                        }
                    }
                }

这在配置中加timeBetweenEvictionRunsMillis:1800000 就能够了,我的理解是一次操做数据库大于这个时间就会被清除,更直观些就是查询或其余操做在数据库执行时间,这里单位是毫秒。测试

紧接着查看源码druid.mysql.usePingMethod=false这个设置,既然网上有人说,就看看好使不,源码以下:ui

 configFromProperties(System.getProperties());
    }

    @Override
    public void configFromProperties(Properties properties) {
        String property = properties.getProperty("druid.mysql.usePingMethod");
        if ("true".equals(property)) {
            setUsePingMethod(true);
        } else if ("false".equals(property)) {
            setUsePingMethod(false);
        }
    }

druid加载System.getProperties(),查看属性中的druid.mysql.usePingMethod的对应值,若是false,就不用ping方法,否者用ping方法,进一步查看不用ping方法就是用默认select 1,System.getProperties()查看了下通常是系统的一些参数,可是能够put(key,value),程序启动时间加载进去就能够,项目中用到了定时器(根据本身项目写就能够,加载一次就ok了),就在初始化时间设置了具体值,代码以下:spa

public void contextInitialized(ServletContextEvent arg0) {
        try {
            System.getProperties().put("druid.mysql.usePingMethod", "false");
            // 获取Scheduler实例
            scheduler = new StdSchedulerFactory().getScheduler();
...

而后取消timeBetweenEvictionRunsMillis设置进行测试,程序跑1个小时没有任何问题,到此问题解决。code

druid我的使用总结:server

1.The last packet successfully received from the server was问题升级jar包,我是升级到1.2.2版本

2.discard long time none received connection问题不应程序状况下设置timeBetweenEvictionRunsMillis参数(注意是毫秒),改程序下加System.getProperties().put("druid.mysql.usePingMethod", "false")

druid默认使用usePingMethod方法,此方法并不会更新链接返回时间,致使lastPacketReceivedTimeMs大于timeBetweenEvictionRunsMillis

网上其余的方法感受要不理解太深,没有给出具体实现,要不就是复制粘贴的,但愿对遇到此问题的人有所帮助。

相关文章
相关标签/搜索