GaussDB与Druid连接池常见问题

举报
HuaweiCloudDeveloper 发表于 2025/07/01 20:34:28 2025/07/01
【摘要】 应用在使用jdbc驱动与GaussDB建立业务操作,使用Druid管理连接池的情况下,掌握常见的问题处理。

1 问题现象

由于GaussDB当前没有自已的JDBC连接池,因此GaussDB建议使用第三方的Druid、Hikari CP、dbcp2等连接池。

2 Druid常见参数

将JDBC驱动包和Druid驱动包添加到工程中,配置数据库连接池相关参数:

参数 默认值 说明

url

-

连接数据库的URL。

username

-

用户名。

password

-

密码。

driverClassName

填写org.postgresql.Driver

数据库驱动名称。

initialSize

0

初始化时建立物理连接的个数。初始化发生在显示调用init方法,或者第一次getConnection时。

maxActive

8

线程池中最大的连接数。

minIdle

0

线程池最小空闲数。Druid会定期扫描连接数情况,如果扫描的值大于该值就关闭多余的连接数,小于就创建符合要求的连接数;这个参数主要应用于突然有大量请求的时候,创建新的连接数,该操作比较耗时。

connectTimeout

-

连接数据库超时时间,单位:ms。

socketTimeout

-

socket连接数据库连接超时时间,单位:ms。

maxWait

-1

连接池中连接用完时,新的请求等待时间,单位:ms。

-1表示无限等待,直到超时为止。

poolPreparedStatements

false

是否缓存preparedStatement,也就是PSCache。PSCache对支持游标的数据库性能提升较大。

maxOpenPreparedStatements

-

启用PSCache,必须配置大于0。

当大于0时,poolPreparedStatements自动触发修改为true。

validationQuery

SELECT 1

用来检测连接是否有效的SQL。

如果validationQuery为空,则testOnBorrow、testOnReturn、testWhileIdle这三个参数都不会起作用,因为这三个参数都是通过执行参数validationQuery指定的SQL来验证数据库连接的有效性。

testOnBorrow

-

申请连接时执行validationQuery检测连接是否有效,这个配置可能会降低性能,请谨慎操作。

testOnReturn

-

归还连接时执行validationQuery检测连接是否有效,这个配置可能会降低性能,请谨慎操作。

testWhileIdle

true

申请连接的时候检测,建议配置为true,不影响性能,并且保证安全性 。如果空闲时间大于timeBetweenEvictionRunMills,执行validationQuery检测连接是否有效都不会起作用。

timeBetweenEvictionRunsMillis

60s

执行validationQuery检测连接是否有效。判断连接池的连接空闲数是否大于minIdle,如果是则关闭多余的连接数,少则会补上(如果当前连接池中某个连接在空闲了timeBetweenEvictionRunsMillis时间后仍然没有使用,则会被物理性关闭掉)。

有两个含义:

  1. Destroy线程会检测连接的间隔时间。
  2. testWhileIdle的判断依据,详细看testWhileIdle属性的说明。

minEvictableIdleTimeMillis

30min

连接保持空闲而不被驱逐的最长存活时间。Destroy线程中如果检测到当前连接的最后活跃时间和当前时间的差值大于minEvictableIdleTimeMillis,则关闭当前连接。

 说明:这个参数和timeBetweenEvictionRunsMillis参数有点冲突,可默认不配置该参数。

connectionInitSqls

-

物理连接初始化的时候执行SQL。

exceptionSorter

-

当数据库抛出一些不可恢复的异常时,抛弃连接。

filters

-

通过别名的方式配置扩展插件,属性类型是字符串。常用的插件有监控统计用的filter:

  • stat:监控统计。
  • log4j:日志记录。
  • wall:防御sql注入。

proxyFilters

-

类型是List<com.alibaba.druid,filter.Filter>,可同时配置filter和proxyFilters,这两个是组合关系。

removeAbandoned

false

如果连接泄露,是否需要回收泄露的连接。

在getNumActive()快要到getMaxActive()的时候,系统会进行无效的连接回收,回收的连接为removeAbandonedTimeout(默认300秒)中设置的秒数后没有使用的连接; 对于建立时间超过removeAbandonedTimeout的连接强制关闭。

removeAbandonedTimeout

300s

设置Druid强制回收连接的时限,单位:s。当程序从连接池中得到连接开始算起,指定连接建立多长时间druid将强制回收该连接。

logAbandoned

false

如果回收泄露的连接,是否要打印一条log。

指定发生removeabandoned的时候,是否记录当前线程的堆栈信息到日志中。

removeAbandonedTimeoutMillis

5min

连接回收的超时时间。设置“removeAbandoned”为“true”,Druid会定期检查线程池溢出的情况,如果不是运行状态,且超过设置的时间就会被回收。

maxEvictableIdleTimeMillis

7hours

最大空闲时间,默认为7小时。

maxPoolPrepareStatementPerConnectionSize

20

每个连接最多缓存的SQL数。

keepAlive

false

初始化连接池时会填充到minIdle的数量。

连接池中的minIdle数量以内的连接,空闲时间超过minEvictableIdleTimeMillis时,则会执行keepAlive操作,打开会一直保持minIdle的数量值。

notFullTimeoutRetryCount

0

连接池内借出的连接加上可用连接小于最大连接数时,则进行重试操作次数,默认为0。

logSlowSql

false

是否打印慢SQL。

3 测试案例

此案例使用select pg_sleep函数产生一个12秒长事务。

package client;
import com.alibaba.druid.pool.DruidDataSource;
import com.alibaba.druid.pool.DruidPooledConnection;
import java.sql.Connection;
import java.sql.PreparedStatement;
/**
* @version [1.0]
* @Author .wx
* @Date 2024/8/7 19:55
* @description
*/
public class TestDruid {
private static final String username="xxxx";
private static final String passwd="xxxx";
private static final String driver="org.postgresql.Driver";
private static final String sourceURL="jdbc:postgresql://xxx.xx.xx.xx.xxx:17777,xxx.xx.xx.xx.xxx:17777,xxx.xx.xx.xx.xxx:17777/xxxx?" +
     "connectTimeout=5&socketTimeout=60";
     public static void test(){
     DruidPooledConnection connection = null;
     try {
     DruidDataSource druidDataSource = new DruidDataSource();
     druidDataSource.setUrl(sourceURL);
     druidDataSource.setUsername(username);
     druidDataSource.setPassword(passwd);
     druidDataSource.setDriverClassName(driver);
     druidDataSource.setTestWhileIdle(true); //是否空闲检测
     druidDataSource.setValidationQuery("select 1");//检测sql
     druidDataSource.setValidationQueryTimeout(3000);//检测sql的超时时长
     druidDataSource.setTimeBetweenEvictionRunsMillis(34000);//检测间隔时长 ms
     druidDataSource.setInitialSize(1);//初始化连接
     druidDataSource.setMinIdle(1);//最小连接
     druidDataSource.setMaxActive(5);//最大活跃数(连接数)
     druidDataSource.setMaxWait(3000);//获取连接的最大等待时间
     druidDataSource.setMaxEvictableIdleTimeMillis(60000);//连接在连接池中最长的空闲时间,超过这个时间的连接将被强制回收
     druidDataSource.setMinEvictableIdleTimeMillis(30000);//连接在连接池中最短的空闲时间,连接池中的连接空闲时间低于这个时间将不会被回收
     druidDataSource.setTestOnBorrow(false);//是否在获取连接时验证连接有效性
     druidDataSource.setTestOnReturn(false);//是否在归还连接时验证连接有效性。
     //druidDataSource.setSocketTimeout(60000);
     //druidDataSource.setConnectTimeout(5000);
     //druidDataSource.setKeepAlive(true);//网络层
     //druidDataSource.setKeepAliveBetweenTimeMillis(20000);
     connection = druidDataSource.getConnection();
     //执行业务完成后,关闭此连接后会将连接放入连接池成为空闲连接
     connection.close();
     Thread.sleep(32000);
     //再次取出连接
     connection = druidDataSource.getConnection();
     System.out.println("socketTimeout时间为:"+connection.getNetworkTimeout());
     PreparedStatement preparedStatement = connection.prepareStatement("select pg_sleep(12)");
     preparedStatement.executeQuery();//执行sql
     System.out.println("sql执行完成");
     preparedStatement.close();
     connection.close();
     }catch (Exception e){
     e.printStackTrace();
     }
   }

    

     public static void main(String[] args) {

     test();

     }

    }

4 常见问题处理

1、 socket is closed; Sending Urgent packet failed, detail: Socket Closed. An I/O error occurred while sending to the backend.detail:Read timed out;

     a、 连接串配置了socketTimeout连接池没有配置socketTimeout业务执行sql时长并没有超过配置报此错误,德鲁伊版本1.2.151.2.16这两个版本connectTimeoutsocketTimeout都需要设置1.2.171.2.21其他版本此类问题只需要设置socketTimeout

     b、 德鲁伊版本使用1.21之后连接串配置了socketTimeout连接池配置socketTimeout业务执行sql时长并没有超过此配置报此错误

2、 socket is not closed; Urgent packet sent to backend successfully; An I/O error occured while sending to the backend.detail:EOF Exception;

     a、 修改连接池配置调整TimeBetweenEvictionRunsMillis参数检测时长。

    b、 修改数据库session_timeout

5 简单总结

应用在使用jdbc驱动与GaussDB建立业务操作,使用Druid管理连接池的情况下,掌握常见的问题处理。

【声明】本内容来自华为云开发者社区博主,不代表华为云及华为云开发者社区的观点和立场。转载时必须标注文章的来源(华为云社区)、文章链接、文章作者等基本信息,否则作者和本社区有权追究责任。如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@huaweicloud.com
  • 点赞
  • 收藏
  • 关注作者

评论(0

0/1000
抱歉,系统识别当前为高风险访问,暂不支持该操作

全部回复

上滑加载中

设置昵称

在此一键设置昵称,即可参与社区互动!

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。