文章详情

短信预约-IT技能 免费直播动态提醒

请输入下面的图形验证码

提交验证

短信预约提醒成功

discard long time none received connection

2023-09-02 13:29

关注

问题:

在用在Spring Boot集成Druid项目中,发现日志出现如下错误信息:

discard long time none received connection.  jdbcUrl : jdbc:mysql://localhost:3306/test?autoReconnect=true&useUnicode=true&characterEncoding=utf8&serverTimezone=CTT,  jdbcUrl : jdbc:mysql://localhost:3306/test?autoReconnect=true&useUnicode=true&characterEncoding=utf8&serverTimezone=CTT,  lastPacketReceivedIdleMillis : 31990

虽然并不影响程序正常运行,但有错误终归是不好的

分析:

从com.alibaba.druid.pool.DruidAbstractDataSource#testConnectionInternal抛出的异常点入看

 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
                    + ", jdbcUrl : " + jdbcUrl
                    + ", lastPacketReceivedIdleMillis : " + mysqlIdleMillis;
            LOG.error(errorMsg);
            return false;
        }
    }
}

上述代码中,MySqlUtils.getLastPacketReceivedTimeMs(conn) 是获取上一次使用的时间,mysqlIdleMillis 就是计算出来空闲的时间,而timeBetweenEvictionRunsMillis 是常量60秒。也就是说如果连接空闲了60秒以上,那就会discardConnection(holder) 丢弃这个旧连接并顺带打印了一个日志LOG.warn(errorMsg)。


解决:

可以看到valid && isMySql都为true就会进入该方法,而isMySql是必然为true的,因为使用的就是MySQL数据。那就是让valid为false,继续点进去valid看方法来源

boolean valid = validConnectionChecker.isValidConnection(conn, validationQuery, validationQueryTimeout);

继续进入isValidConnection方法看看,找到validConnectionChecker的Mysql实现子类MySqlValidConnectionChecker,该类中对isValidConnection的实现如下

public boolean isValidConnection(Connection conn, String validateQuery, int validationQueryTimeout) throws Exception {
    if (conn.isClosed()) {
        return false;
    }

    if (usePingMethod) {
        if (conn instanceof DruidPooledConnection) {
            conn = ((DruidPooledConnection) conn).getConnection();
        }

        if (conn instanceof ConnectionProxy) {
            conn = ((ConnectionProxy) conn).getRawObject();
        }

        if (clazz.isAssignableFrom(conn.getClass())) {
            if (validationQueryTimeout <= 0) {
                validationQueryTimeout = DEFAULT_VALIDATION_QUERY_TIMEOUT;
            }

            try {
                ping.invoke(conn, true, validationQueryTimeout * 1000);
            } catch (InvocationTargetException e) {
                Throwable cause = e.getCause();
                if (cause instanceof SQLException) {
                    throw (SQLException) cause;
                }
                throw e;
            }
            return true;
        }
    }

    String query = validateQuery;
    if (validateQuery == null || validateQuery.isEmpty()) {
        query = DEFAULT_VALIDATION_QUERY;
    }

    Statement stmt = null;
    ResultSet rs = null;
    try {
        stmt = conn.createStatement();
        if (validationQueryTimeout > 0) {
            stmt.setQueryTimeout(validationQueryTimeout);
        }
        rs = stmt.executeQuery(query);
        return true;
    } finally {
        JdbcUtils.close(rs);
        JdbcUtils.close(stmt);
    }

}
 

我们可以看到上述方法中有三个返回的地方:第一个连接已关闭;第二个使用ping的形式进行检查;第三,使用select 1的方式进行检查。而使用ping的形式检查时,无论是否抛异常都会返回true。这里我们禁用该模式即可。

然后进入到ping的方法

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.mysql.usePingMethod设置为false即可禁用该功能

找到druid的配置

 添加上use-ping-method: false就好了

原因:

要设置空闲等待时间60秒后没有连接就断开大概是因为优化数据库处理能力而MySQL的默认空闲等待时间是8小时。如果数据库主动关闭了空闲的连接,而连接池还在使用这个连接,就会产生异常。

参考文章:

(1条消息) Spring Boot集成Druid异常discard long time none received connection._程序新视界的博客-CSDN博客_discard long time none received connection.

来源地址:https://blog.csdn.net/m0_62314761/article/details/129154491

阅读原文内容投诉

免责声明:

① 本站未注明“稿件来源”的信息均来自网络整理。其文字、图片和音视频稿件的所属权归原作者所有。本站收集整理出于非商业性的教育和科研之目的,并不意味着本站赞同其观点或证实其内容的真实性。仅作为临时的测试数据,供内部测试之用。本站并未授权任何人以任何方式主动获取本站任何信息。

② 本站未注明“稿件来源”的临时测试数据将在测试完成后最终做删除处理。有问题或投稿请发送至: 邮箱/279061341@qq.com QQ/279061341

软考中级精品资料免费领

  • 历年真题答案解析
  • 备考技巧名师总结
  • 高频考点精准押题
  • 2024年上半年信息系统项目管理师第二批次真题及答案解析(完整版)

    难度     807人已做
    查看
  • 【考后总结】2024年5月26日信息系统项目管理师第2批次考情分析

    难度     351人已做
    查看
  • 【考后总结】2024年5月25日信息系统项目管理师第1批次考情分析

    难度     314人已做
    查看
  • 2024年上半年软考高项第一、二批次真题考点汇总(完整版)

    难度     433人已做
    查看
  • 2024年上半年系统架构设计师考试综合知识真题

    难度     221人已做
    查看

相关文章

发现更多好内容

猜你喜欢

AI推送时光机
位置:首页-资讯-数据库
咦!没有更多了?去看看其它编程学习网 内容吧
首页课程
资料下载
问答资讯