druid数据源检测数据库连接有效性testOnBorrow、testOnReturn、t。。。

更新时间:2023-05-22 22:04:53 阅读: 评论:0

druid数据源检测数据库连接有效性testOnBorrow、testOnReturn、t。。。
druid多数据源建⽴连接后,可以通过配置对连接的有效性进⾏检查,想要更好的运⽤好数据库连接检查配置就应该了解源码,了解控制原理。
druid多数据源检测数据库连接的有效性属性配置如下:
#mysql默认使⽤ping模式,可以通过设置系统属性Properties().tProperty("sql.uPingMethod", "fal")更改为sql模式
#⽤来检测连接是否有效的sql,要求是⼀个查询语句,常⽤lect 'x'。如果validationQuery为null,testOnBorrow、testOnReturn、testWhileIdle都不会起作⽤。默认:SELECT 1
#单位:秒,检测连接是否有效的超时时间。底层调⽤jdbc Statement对象的void tQueryTimeout(int conds)⽅法,默认:-1
#申请连接时执⾏validationQuery检测连接是否有效,这个配置会降低性能。默认:fal(如果test-on-borrow为true,那么test-while-idle⽆效)
#建议配置为true,不影响性能,并且保证安全性。申请连接的时候检测,如果空闲时间⼤于timeBetweenEvictionRunsMillis,执⾏validationQuery检测连接是否有效。默认:true
#归还连接时执⾏validationQuery检测连接是否有效,做了这个配置会降低性能。默认:fal
获取数据库连接DruidPooledConnection对象⼊⼝代码com.alibaba.druid.pool.DruidDataSource#getConnection()
@Override
public DruidPooledConnection getConnection()throws SQLException {
return getConnection(maxWait);
}
public DruidPooledConnection getConnection(long maxWaitMillis)throws SQLException {
//对数据库连接池进⾏初始化
init();
if(filters.size()>0){
FilterChainImpl filterChain =new FilterChainImpl(this);
return filterChain.dataSource_connect(this, maxWaitMillis);
}el{
//获取数据库连接对象
return getConnectionDirect(maxWaitMillis);
}
}
com.alibaba.druid.pool.DruidDataSource#init初始化⽅法会对ValidConnectionChecker接⼝的实现类进⾏初始化
private void initValidConnectionChecker(){
if(this.validConnectionChecker !=null){
return;
}
String realDriverClassName = Class().getName();
if(JdbcUtils.isMySqlDriver(realDriverClassName)){
this.validConnectionChecker =new MySqlValidConnectionChecker();
}el if(realDriverClassName.equals(JdbcConstants.ORACLE_DRIVER)
|| realDriverClassName.equals(JdbcConstants.ORACLE_DRIVER2)){
this.validConnectionChecker =new OracleValidConnectionChecker();
}el if(realDriverClassName.equals(JdbcConstants.SQL_SERVER_DRIVER)
|| realDriverClassName.equals(JdbcConstants.SQL_SERVER_DRIVER_SQLJDBC4)
|| realDriverClassName.equals(JdbcConstants.SQL_SERVER_DRIVER_JTDS)){
this.validConnectionChecker =new MSSQLValidConnectionChecker();爱情机器
胜利用英语怎么说
}el if(realDriverClassName.equals(JdbcConstants.POSTGRESQL_DRIVER)马说ppt
|| realDriverClassName.equals(JdbcConstants.ENTERPRISEDB_DRIVER)
|| realDriverClassName.equals(JdbcConstants.POLARDB_DRIVER)){
this.validConnectionChecker =new PGValidConnectionChecker();
}
}
此⽅法分别对不同种类的数据库连接检测有效性的实现类进⾏初始化,接下来会在建⽴连接、归还链接过程中⽤到;
com.alibaba.druid.pool.DruidDataSource#getConnectionDirect⽅法是获取数据库连接的具体实现:
public DruidPooledConnection getConnectionDirect(long maxWaitMillis)throws SQLException {
int notFullTimeoutRetryCnt =0;
for(;;){
// handle notFullTimeoutRetry
DruidPooledConnection poolableConnection;
try{
//从数据库连接池中获取连接对象句柄
poolableConnection =getConnectionInternal(maxWaitMillis);
}catch(GetConnectionTimeoutException ex){
if(notFullTimeoutRetryCnt <=FullTimeoutRetryCount &&!isFull()){
企业所得税计算方法notFullTimeoutRetryCnt++;
if(LOG.isWarnEnabled()){
LOG.warn("get connection timeout retry : "+ notFullTimeoutRetryCnt);
}
continue;
}
throw ex;
}
//如果开启了获取连接有效性检查,则进⾏有效性检查
if(testOnBorrow){
//有效性检查
boolean validate =testConnectionInternal(poolableConnection.holder, );
if(!validate){
if(LOG.isDebugEnabled()){
LOG.debug("skip not validate connection.");
}
discardConnection(poolableConnection.holder);
continue;
}
有时朝发白帝}el{
isClod()){
discardConnection(poolableConnection.holder);// 传⼊null,避免重复关闭
continue;
}
}
//如果testOnBorrow为fal,且testWhileIdle为ture,则在判定连接在空闲时间⼤于timeBetweenEvictionRunsMillis(⼼跳检查时间)时才做判定,对性能损耗⼏乎为0
if(testWhileIdle){
final DruidConnectionHolder holder = poolableConnection.holder;
long currentTimeMillis            = System.currentTimeMillis();
long lastActiveTimeMillis          = holder.lastActiveTimeMillis;
long lastExecTimeMillis            = holder.lastExecTimeMillis;
long lastKeepTimeMillis            = holder.lastKeepTimeMillis;
if(checkExecuteTime
&& lastExecTimeMillis != lastActiveTimeMillis){
lastActiveTimeMillis = lastExecTimeMillis;
}
if(lastKeepTimeMillis > lastActiveTimeMillis){
lastActiveTimeMillis = lastKeepTimeMillis;
}
long idleMillis                    = currentTimeMillis - lastActiveTimeMillis;
long timeBetweenEvictionRunsMillis =this.timeBetweenEvictionRunsMillis;
if(timeBetweenEvictionRunsMillis <=0){
timeBetweenEvictionRunsMillis = DEFAULT_TIME_BETWEEN_EVICTION_RUNS_MILLIS;
}
//连接空闲时间⼤于等于守护线程中⼼跳间隔时间时才进⾏有效性检查
指字开头的成语if(idleMillis >= timeBetweenEvictionRunsMillis
|| idleMillis <0// unexcepted branch
肉末茄子煲
){
boolean validate =testConnectionInternal(poolableConnection.holder, );
if(!validate){
if(LOG.isDebugEnabled()){
LOG.debug("skip not validate connection.");
}
discardConnection(poolableConnection.holder);
continue;
}
}
}
}
if(removeAbandoned){
StackTraceElement[] stackTrace = Thread.currentThread().getStackTrace();
poolableConnection.tConnectedTimeNano();
activeConnectionLock.lock();
try{
activeConnections.put(poolableConnection, PRESENT);
}finally{
activeConnectionLock.unlock();
}
}
if(!this.defaultAutoCommit){
poolableConnection.tAutoCommit(fal);
}
return poolableConnection;
}
}
com.alibaba.druid.pool.DruidAbstractDataSource#testConnectionInternal(com.alibaba.druid.pool.DruidConnectionHolder, java.sql.Connection)⽅法对从数据库中获取到的连接有效性进⾏检查
protected boolean testConnectionInternal(DruidConnectionHolder holder, Connection conn){
String sqlFile = ContextSqlFile();
String sqlName = ContextSqlName();
if(sqlFile !=null){
JdbcSqlStat.tContextSqlFile(null);
}
if(sqlName !=null){
JdbcSqlStat.tContextSqlName(null);
}
try{
//validConnectionChecker属性是init⽅法中对各数据库驱动进⾏初始化的有效性检查实现类
if(validConnectionChecker !=null){
//对连接进⾏有效性检查
boolean valid = validConnectionChecker.isValidConnection(conn, validationQuery, validationQueryTimeout);
...
}
对mysql数据源进⾏连接有效性检查实现类MySqlValidConnectionChecker源码分析
public class MySqlValidConnectionChecker extends ValidConnectionCheckerAdapter implements ValidConnectionChecker, Serializable {
public static final int DEFAULT_VALIDATION_QUERY_TIMEOUT =1;
public static final String DEFAULT_VALIDATION_QUERY ="SELECT 1";
private static final long rialVersionUID =1L;
private static final Log  LOG              = Log(MySqlValidConnectionChecker.class);
private Class<?> clazz;
private Method  ping;
private boolean  uPingMethod =fal;
public MySqlValidConnectionChecker(){
try{
//8.0之前的mysql驱动
clazz = Utils.loadClass("sql.jdbc.MySQLConnection");
if(clazz ==null){
//8.0之后的驱动
clazz = Utils.loadClass("sql.cj.jdbc.ConnectionImpl");
}
if(clazz !=null){
//获取pingInternal⽅法⽰例
ping = Method("pingInternal",boolean.class,int.class);
}
if(ping !=null){
//实际是使⽤ping模式检测连接有效性
uPingMethod =true;
}
}catch(Exception e){
LOG.warn("Cannot sql.jdbc.Connection.ping method.  Will u 'SELECT 1' instead.", e);
}
Properties());
}
@Override
public void configFromProperties(Properties properties){
if(properties ==null){
return;
}
}言行举止的意思是什么
//根据系统属性设置判定连接有效性的⽅法
String property = Property("sql.uPingMethod");
if("true".equals(property)){
tUPingMethod(true);
}el if("fal".equals(property)){
tUPingMethod(fal);
}
}
public boolean isUPingMethod(){
return uPingMethod;
}
public void tUPingMethod(boolean uPingMethod){
this.uPingMethod = uPingMethod;
}
public boolean isValidConnection(Connection conn, String validateQuery,int validationQueryTimeout)throws Exception { if(conn.isClod()){
return fal;
}
if(uPingMethod){
if(conn instanceof DruidPooledConnection){
conn =((DruidPooledConnection) conn).getConnection();
}
if(conn instanceof ConnectionProxy){
conn =((ConnectionProxy) conn).getRawObject();
}
if(clazz.Class())){
if(validationQueryTimeout <=0){
validationQueryTimeout = DEFAULT_VALIDATION_QUERY_TIMEOUT;
}
try{
//使⽤ping的⽅式判定连接有效性
ping.invoke(conn,true, validationQueryTimeout *1000);
}catch(InvocationTargetException e){
Throwable cau = e.getCau();
if(cau instanceof SQLException){
throw(SQLException) cau;
}
throw e;
}
return true;
}
}
String query = validateQuery;
if(validateQuery ==null|| validateQuery.isEmpty()){
query = DEFAULT_VALIDATION_QUERY;
}
Statement stmt =null;
ResultSet rs =null;
try{
//使⽤sql的⽅式校验连接的有效性
stmt = ateStatement();
if(validationQueryTimeout >0){
stmt.tQueryTimeout(validationQueryTimeout);
}
rs = uteQuery(query);

本文发布于:2023-05-22 22:04:53,感谢您对本站的认可!

本文链接:https://www.wtabcd.cn/fanwen/fan/82/737113.html

版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系,我们将在24小时内删除。

标签:连接   有效性   检测   数据库   检查
相关文章
留言与评论(共有 0 条评论)
   
验证码:
推荐文章
排行榜
Copyright ©2019-2022 Comsenz Inc.Powered by © 专利检索| 网站地图