开发者社区> 问答> 正文

TestWhileIdle=true的情况下空闲连接失效

配置:

testWhileIdle=true testOnBorrow=false testOnReturn=false keepAlive=true

mysql服务端wait_timeout=60分钟。 默认情况下, 每60秒通过"select 1‘’检测一次空闲连接。 然而, 部分空闲连接依然给mysql杀掉。

从mysql看空闲的连接的情况, select * from infomation_schema.processlist order by time desc limit 10; 发现大量的连接空闲时间超过10几分钟(Command=Sleep)。(理论上空闲时间不超过1分钟)

开启mysql的日志, 没发现保活查询语句select 1 在客户端抓包, 也常时间没发现有tcp包发往mysql。

查询代码MySqlValidConnectionChecker.isValidConnection, 发现即使配置了validationQuery, 保活机制依然默认采用mysql_ping。

这个设置很不合理且没有文档说明。 这个机制只能用于检测连接是否有效,对于testOnBorrow来说可能比较合适。 但对于testWhileIdle来说, 并不起作用,因为它不会重置连接的空闲时间。

1.1.14? 看代码最新版本也是一样的

而且, 禁用usePingMethod这个参数,并没有在wiki上说明。

禁用usePingMethod后,经过调试发现,客户端30分钟才会发一次SELECT 1, 预期是1分钟(默认配置)(update: 30分钟才发心跳,是因为minEvictableIdleTimeMillis设置了30分钟。。)。 并且, 配置了MinIdle是30, 最后只剩下一条连接了!

T33.png

原提问者GitHub用户zhangever

展开
收起
山海行 2023-07-05 19:31:13 172 0
2 条回答
写回答
取消 提交回答
  • 北京阿里云ACE会长

    主要可能的原因有几种:

    数据库本身关闭或挂起了连接
    部分数据库在一段时间内没有活动后,会自动关闭或挂起连接。

    这时即使Druid检验了连接,也会发现连接已失效。

    检查时数据库不可用,造成校验失败
    如果在Druid校验连接时,数据库短暂不可用,这时校验也会失败,标识连接失效。

    TestWhileIdle配置不合理
    如果timeBetweenEvictionRunsMillis(校验间隔)设置太长,就可能间隔时间内数据库主动断开连接。

    数据库配置限制了空闲连接的存活时间
    部分数据库可以配置空闲连接的存活时间,当超过设置值后会自动失效。

    2023-07-30 17:12:14
    赞同 展开评论 打赏
  • 最终结论: 心跳方式不管是mysql_ping还是SELECT 1, 都可以重置连接的空闲时间。 然后,保活线程是1分钟执行一次,但只对空闲时间超过minEvictableIdleTimeMillis的连接发心跳。

    我们之前minEvictableIdleTimeMillis设置是30分钟, 所以30分钟才会看到一次心跳。 而mysql服务端不知道为何, 对于超过30分钟的连接会直接kill掉。

    原回答者GitHub用户zhangever

    2023-07-06 11:00:40
    赞同 展开评论 打赏
问答排行榜
最热
最新

相关电子书

更多
低代码开发师(初级)实战教程 立即下载
冬季实战营第三期:MySQL数据库进阶实战 立即下载
阿里巴巴DevOps 最佳实践手册 立即下载