Druid 连接池食用教程

1 参数 initialSize

连接池初始化时,会调用 com.alibaba.druid.pool.DruidDataSource#init 初始化连接池的数据库连接

while (poolingCount < initialSize) {
  try {
     // 初始化物理连接
     PhysicalConnectionInfo pyConnectInfo = createPhysicalConnection();
     DruidConnectionHolder holder = new DruidConnectionHolder(this, pyConnectInfo);
     connections[poolingCount++] = holder;
  } catch (SQLException ex) {
      LOG.error("init datasource error, url: " + this.getUrl(), ex);
  }
}

2 校验连接

com.alibaba.druid.pool.vendor.MySqlValidConnectionChecker#isValidConnection

public static final String DEFAULT_VALIDATION_QUERY = "SELECT 1";
private Method   ping;
private boolean  usePingMethod = false;

public MySqlValidConnectionChecker(){
        try {
            clazz = Utils.loadClass("com.mysql.jdbc.MySQLConnection");
            if (clazz == null) {
                clazz = Utils.loadClass("com.mysql.cj.jdbc.ConnectionImpl");
            }

            if (clazz != null) {
                ping = clazz.getMethod("pingInternal", boolean.class, int.class);
            }
            // ping 方法是 mysql-connector-java 包自带的方法,不会为空
            if (ping != null) {
                usePingMethod = true;
            }
        } catch (Exception e) {
            LOG.warn("Cannot resolve com.mysql.jdbc.Connection.ping method.  Will use 'SELECT 1' instead.", e);
        }
        configFromProperties(System.getProperties());
}

public boolean isValidConnection(Connection conn, String validateQuery, int validationQueryTimeout) throws Exception {
        // 通过 ping 的方式
        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);
            }
            // 通过执行探活 sql
            rs = stmt.executeQuery(query);
            return true;
        } finally {
            JdbcUtils.close(rs);
            JdbcUtils.close(stmt);
        }
}

Druid + MySQL 默认使用 ping 的方式去判断连接是否有效,导致项目配置的 validationQuery 不会执行

解决方案 1:

在进程的启动参数中(jvm参数)设置 -Ddruid.mysql.usePingMethod=false 

解放方案 2: 自定义 ValidConnectionChecker

@Slf4j
public class MySqlReplicationValidConnectionChecker extends ValidConnectionCheckerAdapter implements ValidConnectionChecker, Serializable {}

如果项目整合了 shardingJDBC,Druid 执行探活 sql 时,底层不走shardingJDBC。

org.apache.shardingsphere.shardingjdbc.jdbc.core.statement.ShardingStatement 执行sql相关方法时才会走 shardingJDBC 全套流程

3 其他参数列表

配置缺省值说明
poolPreparedStatementsfalse是否缓存preparedStatement,也就是PSCache。PSCache对支持游标的数据库性能提升巨大,比如说oracle。在mysql下建议关闭。
maxOpenPreparedStatements-1要启用PSCache,必须配置大于0,当大于0时,poolPreparedStatements自动触发修改为true。在Druid中,不会存在Oracle下PSCache占用内存过多的问题,可以把这个数值配置大一些,比如说100。
validationQuery 用来检测连接是否有效的sql,要求是一个查询语句。如果validationQuery为null,testOnBorrow、testOnReturn、testWhileIdle都不会其作用。
testOnBorrowtrue申请连接时执行validationQuery检测连接是否有效,做了这个配置会降低性能。
testOnReturnfalse归还连接时执行validationQuery检测连接是否有效,做了这个配置会降低性能。
testWhileIdlefalse建议配置为true,不影响性能,并且保证安全性。申请连接的时候检测,如果空闲时间大于 timeBetweenEvictionRunsMillis,执行validationQuery检测连接是否有效。

keepAlive

 是否对空闲连接保活。
timeBetweenEvictionRunsMillis Destroy 线程检测连接的间隔时间,会在检测过程中触发心跳,其中心跳检查会根据配置使用 ping 或 validationQuery 配置的检查语句。
minEvictableIdleTimeMillis 连接保持空闲而不被驱逐的最小时间。
maxEvictableIdleTimeMillis 连接保持空闲而不被驱逐的最长时间。
connectionInitSqls 物理连接初始化的时候执行的sql。

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值