Druid配置参数详解-validationQuery

Druid是一个由阿里开源的数据库连接池,Druid的配置非常丰富,但是设置不当会对生产环境造成严重影响,网上Druid的资料虽多,但大部分都是互相复制粘贴,有很多不准确甚至完全错误的描述,Druid已经开源很久,而且作者WenShao的工作重心也已经不在Druid上,有些功能估计他自己都不太了解了。本系列将从源代码的角度分析Druid目前的最新版本(1.1.21)各个常用的配置项的具体含义以及是怎么起作用的。

画外音:目前Druid在开源中国举办的2019年度最受欢迎中国开源软件中排名第7名,支持Druid的朋友可以去投票哇。2019年度最受欢迎中国开源软件

validationQuery是什么意思?

validationQuery:Druid用来测试连接是否可用的SQL语句,默认值每种数据库都不相同:

Mysql:SELECT 1;

SQLSERVER:SELECT 1;

ORACLE:SELECT 'x' FROM DUAL;

PostGresql:SELECT 'x';

validationQuery什么时候会起作用?

当Druid遇到testWhileIdle,testOnBorrow,testOnReturn时,就会验证连接的有效性,验证规则如下:

如果有相关数据库的ValidConnectionChecker,则使用ValidConnectionChecker验证(Druid提供常用数据库的ValidConnectionChecker,包括MSSQLValidConnectionChecker,MySqlValidConnectionChecker,OracleValidConnectionChecker,PGValidConnectionChecker);

如果没有ValidConnectionChecker,则直接使用validationQuery验证;

ValidConnectionChecker是如何验证的?

MySqlValidConnectionChecker会使用Mysql独有的ping方式进行验证,其他数据库其实也都是使用validationQuery进行验证

MySqlValidConnectionChecker验证方式

public boolean isValidConnection(Connection conn, String validateQuery, int validationQueryTimeout) throws Exception {

if (conn.isClosed()) {

return false;

}

//Mysql使用com.mysql.jdbc.MySQLConnection的pingInternal方法进行验证

if (usePingMethod) {

if (conn instanceof DruidPooledConnection) {

conn = ((DruidPooledConnection) conn).getConnection();

}

if (conn instanceof ConnectionProxy) {

conn = ((ConnectionProxy) conn).getRawObject();

}

if (clazz.isAssignableFrom(conn.getClass())) {

if (validationQueryTimeout <= 0) {

validationQueryTimeout = DEFAULT_VALIDATION_QUERY_TIMEOUT;

}

try {

ping.invoke(conn, true, validationQueryTimeout * 1000);

} catch (InvocationTargetException e) {

Throwable cause = e.getCause();

if (cause instanceof SQLException) {

throw (SQLException) cause;

}

throw e;

}

return true;

}

}

String query = validateQuery;

if (validateQuery == null || validateQuery.isEmpty()) {

query = DEFAULT_VALIDATION_QUERY;

}

Statement stmt = null;

ResultSet rs = null;

try {

stmt = conn.createStatement();

if (validationQueryTimeout > 0) {

stmt.setQueryTimeout(validationQueryTimeout);

}

rs = stmt.executeQuery(query);

return true;

} finally {

JdbcUtils.close(rs);

JdbcUtils.close(stmt);

}

}

OracleValidConnectionChecker的验证方式

public boolean isValidConnection(Connection conn, String validateQuery, int validationQueryTimeout) throws Exception {

if (validateQuery == null || validateQuery.isEmpty()) {

validateQuery = this.defaultValidateQuery;

}

if (conn.isClosed()) {

return false;

}

if (conn instanceof DruidPooledConnection) {

conn = ((DruidPooledConnection) conn).getConnection();

}

if (conn instanceof ConnectionProxy) {

conn = ((ConnectionProxy) conn).getRawObject();

}

if (validateQuery == null || validateQuery.isEmpty()) {

return true;

}

int queryTimeout = validationQueryTimeout <= 0 ? timeout : validationQueryTimeout;

Statement stmt = null;

ResultSet rs = null;

try {

stmt = conn.createStatement();

stmt.setQueryTimeout(queryTimeout);

rs = stmt.executeQuery(validateQuery);

return true;

} finally {

JdbcUtils.close(rs);

JdbcUtils.close(stmt);

}

}

SqlServer的验证方式

public boolean isValidConnection(final Connection c, String validateQuery, int validationQueryTimeout) throws Exception {

if (c.isClosed()) {

return false;

}

Statement stmt = null;

try {

stmt = c.createStatement();

if (validationQueryTimeout > 0) {

stmt.setQueryTimeout(validationQueryTimeout);

}

stmt.execute(validateQuery);

return true;

} catch (SQLException e) {

throw e;

} finally {

JdbcUtils.close(stmt);

}

}

总结

不同数据库的默认值不同;

如果是Mysql数据库,则validationQuery不会起作用,Mysql会使用ping的方式验证;

Copyright © 2088 俄罗斯世界杯主题曲_世界杯下一届 - pin8pin8.com All Rights Reserved.
友情链接