使用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内的空闲连接,每次检查强制验证连接有效性
<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不宜设置的过于频繁。