美文网首页
Druid配置参数详解-validationQuery

Druid配置参数详解-validationQuery

作者: codeimport | 来源:发表于2020-01-03 14:49 被阅读0次

    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的方式验证;

    相关文章

      网友评论

          本文标题:Druid配置参数详解-validationQuery

          本文链接:https://www.haomeiwen.com/subject/jjbzoctx.html