使用Durid连接池出现wait

    科技2026-01-06  9

    使用Durid连接池出现wait_timeout错误分析

    前言Durid连接池核心的配置总结参考资料

    前言

    最近其他团队使用hive的jdbcTemplate操作的时候出现了wait_timeout错误,经过定位是因为mysql数据库的wait_timeout设置的时间为1800秒(默认为28800秒即8个小时)。hive的元数据是存在mysql当中的,hiveserver默认的连接池是bonecp(新版本改成了HikariCP),当前使用的hive版本只对连接池的几个配置项作为参数值进行设置(连接超时时间、最大连接数、分区数、用户、密码),其他均使用的连接池默认配置。而连接池的探活时间配置目前还未作为配置项(因此当前机制使用的是连接池默认的 4 小时)。 由此也研究下项目中用到的Durid连接池。

    Durid连接池核心的配置

    Durid连接池一般有几个核心的配置:

    <!-- 配置初始化大小、最小、最大 --> <property name="initialSize" value="5" /> <property name="minIdle" value="5" /> <property name="maxActive" value="10" /> <!-- 配置从连接池获取连接等待超时的时间 --> <property name="maxWait" value="10000" /> <!-- 配置间隔多久启动一次DestroyThread,对连接池内的连接才进行一次检测,单位是毫秒。 检测时:1.如果连接空闲并且超过minIdle以外的连接,如果空闲时间超过minEvictableIdleTimeMillis设置的值则直接物理关闭。2.在minIdle以内的不处理。 --> <property name="timeBetweenEvictionRunsMillis" value="60000" /> <!-- 配置一个连接在池中最大空闲时间,单位是毫秒 --> <property name="minEvictableIdleTimeMillis" value="300000" /> <!-- 设置从连接池获取连接时是否检查连接有效性,true时,每次都检查;false时,不检查 --> <property name="testOnBorrow" value="false" /> <!-- 设置往连接池归还连接时是否检查连接有效性,true时,每次都检查;false时,不检查 --> <property name="testOnReturn" value="false" /> <!-- 设置从连接池获取连接时是否检查连接有效性,true时,如果连接空闲时间超过minEvictableIdleTimeMillis进行检查,否则不检查;false时,不检查 --> <property name="testWhileIdle" value="true" /> <!-- 检验连接是否有效的查询语句。如果数据库Driver支持ping()方法,则优先使用ping()方法进行检查,否则使用validationQuery查询进行检查。(Oracle jdbc Driver目前不支持ping方法) --> <property name="validationQuery" value="select 1 from dual" /> <!-- 打开后,增强timeBetweenEvictionRunsMillis的周期性连接检查,minIdle内的空闲连接,每次检查强制验证连接有效性. 参考:https://github.com/alibaba/druid/wiki/KeepAlive_cn --> <property name="keepAlive" value="true" />

    其中几个关键的逻辑:

    timeBetweenEvictionRunsMillis是调度间隔的时间,会检查非核心连接,如果空闲时间超过minEvictableIdleTimeMillis设置的值则直接物理关闭。testWhileIdle建议开启,每次从连接池中获取连接的时候,如果连接空闲时间超过minEvicatbleIdleTimeMilies都会检查是否有效,如果失效的话,销毁当前的连接,继续在池中获取可用连接,如果整个池中的连接都是无效的,会创建新的连接。 minEvicatbleIdleTimeMilies配置的时间一般都会小于数据库的wait_timeout (mysql默认是8小时)时间,不会出现连接到数据库的连接是关闭的情况。keepAlive开启后,是增强timeBetweenEvictionRunsMillis的周期性连接检查,minIdle内的空闲连接,每次若空闲时间超过keepAliveBetweenTimeMillis检查强制验证连接有效性,若有效会更新空闲时间。如果失效的话,销毁当前的连接。 主要作用是保持了druid连接池的连接的的活性,同时也保活了数据库的连接池,如果minIdle连接数据较多,会使数据库的可用连接变少。 keepAlive开启后,会减少每次从连接池中获取连接时的检查。 需要注意的是,keepAliveBetweenTimeMillis保活的时间间隔,默认为1分钟,一般不需要更改其配置,如果minEvicatbleIdleTimeMilies小于keepAliveBetweenTimeMillis,会使连接池中的所有连接都在保活,会给数据库造成较大的压力。

    简单的流程如下:

    总结

    综上: 如果设置了testWhileIdle为true,minEvictableIdleTimeMillis不要过大,基本不会出现连接数据库连接是关闭的问题; 如果设置了keepAlive为true,minIdle不宜设置的过大,同时timeBetweenEvictionRunsMillis不宜设置的过于频繁。

    参考资料

    https://github.com/alibaba/druid/wiki/DruidDataSource%E9%85%8D%E7%BD%AE%E5%B1%9E%E6%80%A7%E5%88%97%E8%A1%A8https://github.com/alibaba/druid/wiki/DruidDataSource%E9%85%8D%E7%BD%AE
    Processed: 0.014, SQL: 9