赞
踩
mysql默认使用ping模式,可以通过设置系统属性System.getProperties().setProperty(“druid.mysql.usePingMethod”, “false”)更改为sql模式
用来检测连接是否有效的sql,要求是一个查询语句,常用select ‘x’。如果validationQuery为null,testOnBorrow、testOnReturn、testWhileIdle都不会起作用。默认:SELECT 1
spring.emily.datasource.config.mysql.validation-query: "SELECT 1"
单位:秒,检测连接是否有效的超时时间。底层调用jdbc Statement对象的void setQueryTimeout(int seconds)方法,默认:-1
spring.emily.datasource.config.mysql.validation-query-timeout: -1
#申请连接时执行validationQuery检测连接是否有效,这个配置会降低性能。默认:false(如果test-on-borrow为true,那么test-while-idle无效)
spring.emily.datasource.config.mysql.test-on-borrow: false
#建议配置为true,不影响性能,并且保证安全性。申请连接的时候检测,如果空闲时间大于timeBetweenEvictionRunsMillis,执行validationQuery检测连接是否有效。默认:true
spring.emily.datasource.config.mysql.test-while-idle: true
#归还连接时执行validationQuery检测连接是否有效,做了这个配置会降低性能。默认:false
spring.emily.datasource.config.mysql.test-on-return: false
public DruidPooledConnection getConnectionDirect(long maxWaitMillis) throws SQLException
从数据库链接池中获取后,进行校验,避免失效的链接被使用,造成错误
// handle notFullTimeoutRetry DruidPooledConnection poolableConnection; try { // 核心逻辑 System.out.println("getConnectionInternal"); // 获取的池化数据库链接 poolableConnection = getConnectionInternal(maxWaitMillis); } catch (GetConnectionTimeoutException ex) { if (notFullTimeoutRetryCnt <= this.notFullTimeoutRetryCount && !isFull()) { notFullTimeoutRetryCnt++; if (LOG.isWarnEnabled()) { LOG.warn("get connection timeout retry : " + notFullTimeoutRetryCnt); } continue; } throw ex; } // testOnBorrow =false 每次获取链接都会验证 if (testOnBorrow) { // 发送一条validateSql SELECT 1 boolean validate = testConnectionInternal(poolableConnection.holder, poolableConnection.conn); if (!validate) { if (LOG.isDebugEnabled()) { LOG.debug("skip not validate connection."); } // 如果不可用就回收 discardConnection(poolableConnection.holder); continue; } }
申请链接时候会进行一次验证,比较消耗性能,我的理解是无论是开发环境还是生产环境都不需要打开,Druid 1.2.8版本已经有其他的属性去在获取链接时判断链接的有效性
当连接使用完,调用commit或者rollback方法后,连接池会回收该连接
// 回收链接时候
protected void recycle(DruidPooledConnection pooledConnection)
确保归还的时候链接是有效的,如果无效则会丢弃,丢弃的过程中会用lock锁,造成其他线程的堵塞,
if (testOnReturn) { boolean validate = testConnectionInternal(holder, physicalConnection); if (!validate) { JdbcUtils.close(physicalConnection); destroyCountUpdater.incrementAndGet(this); lock.lock(); try { if (holder.active) { activeCount--; holder.active = false; } closeCount++; } finally { lock.unlock(); } return; } }
每次事务提交或者回滚都会回收链接到连接池中,回收过程对链接判断是否有效,进行验证,浪费性能.
与testOnBorrow一致,个人认为testWhileIdle就是代替testOnBorrow的
public DruidPooledConnection getConnectionDirect(long maxWaitMillis) throws SQLException
如果每次从数据库连接池获取链接都进行验证,性能太差,所以引入了空闲时间,当某个链接获取时,快速的check其是否过期.当判断是过期的链接,则进行校验.
if (testWhileIdle) { final DruidConnectionHolder holder = poolableConnection.holder; long currentTimeMillis = System.currentTimeMillis(); // // 记录该链接最后活动时间 long lastActiveTimeMillis = holder.lastActiveTimeMillis; // 记录该链接最后执行时间 long lastExecTimeMillis = holder.lastExecTimeMillis; // 记录最后心跳时间 long lastKeepTimeMillis = holder.lastKeepTimeMillis; // 是否检查执行时间 checkExecuteTime 默认false if (checkExecuteTime && lastExecTimeMillis != lastActiveTimeMillis) { lastActiveTimeMillis = lastExecTimeMillis; } // 如果最后一次心跳时间 大于 最后活动的时间,则赋值 if (lastKeepTimeMillis > lastActiveTimeMillis) { lastActiveTimeMillis = lastKeepTimeMillis; } // 空闲时间 = 当前时间减去 - 最后活跃的时间 long idleMillis = currentTimeMillis - lastActiveTimeMillis; // 默认60秒 long timeBetweenEvictionRunsMillis = this.timeBetweenEvictionRunsMillis; if (timeBetweenEvictionRunsMillis <= 0) { timeBetweenEvictionRunsMillis = DEFAULT_TIME_BETWEEN_EVICTION_RUNS_MILLIS; } // 如果空闲时间 大于等于 60秒 if (idleMillis >= timeBetweenEvictionRunsMillis || idleMillis < 0 ) { // 发送测试语句 SELECT 1 确保回收的是有效的链接 boolean validate = testConnectionInternal(poolableConnection.holder, poolableConnection.conn); if (!validate) { if (LOG.isDebugEnabled()) { LOG.debug("skip not validate connection."); } // 回收 discardConnection(poolableConnection.holder); continue; } } }
如果每次从数据库连接池获取链接都进行验证,性能太差,这就是原来testOnBorrow的做法.不可取.
所以引入了testWhileIdle,吸取了testOnBorrow的弊端,设计了保活机制,增加了校验的前置判断,对从数据库连接池中获取的链接先进行保活判断,不满足主观的保活判断,再客观判断(就是SELECT 1)
赞
踩
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。