GaussDB_DWS连接池问题排查记录

GaussDB DWS 连接池报错排查记录

问题描述

项目从 MySQL 迁移到华为云 GaussDB DWS 后,每次查询必报如下错误:

复制代码
org.postgresql.util.PSQLException: ERROR: pooler: failed to send set 8 handles.

环境信息:

  • Spring Boot 3.x
  • dynamic-datasource-spring-boot3-starter
  • Druid 连接池
  • JDBC 驱动:postgresql 42.x
  • 数据库:华为云 GaussDB DWS(通过 PgBouncer 连接池代理)

排查过程

第一阶段:怀疑连接池配置问题

现象: 错误信息 pooler: failed to send set X handles,X 的数字不固定(有时是 1,有时是 8)。

初步判断: PgBouncer 连接池处于 transaction 模式,该模式不允许 JDBC 驱动在建立连接时发送 SET 初始化命令。

尝试的方案:

  • 关闭 pool-prepared-statements
  • 修改 validation-query(去掉 FROM DUAL)
  • 修改 JDBC URL 参数(去掉 useSSL、reWriteBatchedInserts 等)
  • 降级 Druid 版本(从 1.2.27 降到 1.2.16/1.2.21)

结果: 均无效,问题依旧。


第二阶段:确认是客户端问题还是服务端问题

关键发现:

  • Navicat 连接正常
  • 同事的另一个项目(Druid 1.2.16)连接正常
  • 本项目(Druid 1.2.27)每次必报错

结论: 服务端没问题,问题出在客户端。

进一步对比:

项目 Druid 版本 postgresql 驱动 是否正常
同事项目 1.2.16 42.3.8 ✅ 正常
本项目 1.2.27 42.7.8 ❌ 报错

第三阶段:排除连接池影响

测试1:原生 JDBC 连接

java 复制代码
String url = "jdbc:postgresql://host:port/db?currentSchema=ruoyi-vue-pro";
Connection conn = DriverManager.getConnection(url, user, password);
Statement stmt = conn.createStatement();
ResultSet rs = stmt.executeQuery("SELECT 1");
// 结果:成功

结论: 原生 JDBC 可以正常连接,说明网络和数据库本身没问题。

测试2:通过连接池执行 SELECT 1

java 复制代码
// 结果:成功

测试3:通过连接池执行 PreparedStatement

java 复制代码
PreparedStatement ps = conn.prepareStatement("SELECT COUNT(*) FROM table WHERE col = ?");
ps.setInt(1, 0);
// 结果:失败,报 failed to send set 8 handles

关键结论: SELECT 1(简单查询)成功,PreparedStatement(带参数查询)失败。问题出在 PreparedStatement 的处理上。


第四阶段:换 HikariCP 验证

将 slave 数据源从 Druid 换成 HikariCP:

yaml 复制代码
slave:
  type: com.zaxxer.hikari.HikariDataSource

结果: 同样报 failed to send set 8 handles,排除是 Druid 特有问题。


第五阶段:对比同事项目配置

仔细对比两个项目的配置,发现关键差异:

配置项 同事项目 本项目
currentSchema 写法 currentSchema=test1 currentSchema=ruoyi-vue-pro
Schema 名称 普通名称 包含连字符 -

根本原因

ruoyi-vue-pro 包含连字符 -,在 PostgreSQL/GaussDB 中,schema 名称包含特殊字符时必须用双引号包裹,否则 GaussDB 连接池在解析时会出错,触发 failed to send set handles 异常。

JDBC URL 中 currentSchema=ruoyi-vue-pro 没有加引号,导致 GaussDB 无法正确识别 schema,进而触发连接池报错。


解决方案

在 JDBC URL 中给 schema 名称加上双引号:

yaml 复制代码
# 修改前(错误)
url: jdbc:postgresql://host:port/twd?currentSchema=ruoyi-vue-pro

# 修改后(正确)
url: jdbc:postgresql://host:port/twd?currentSchema="ruoyi-vue-pro"

# 或者使用 URL 编码
url: jdbc:postgresql://host:port/twd?currentSchema=%22ruoyi-vue-pro%22

完整的推荐配置

yaml 复制代码
spring:
  autoconfigure:
    exclude:
      - com.alibaba.druid.spring.boot.autoconfigure.DruidDataSourceAutoConfigure
  datasource:
    dynamic:
      primary: master
      datasource:
        master:
          driver-class-name: com.mysql.cj.jdbc.Driver
          url: jdbc:mysql://host:port/db?useSSL=false&serverTimezone=Asia/Shanghai&allowPublicKeyRetrieval=true&rewriteBatchedStatements=true
          username: xxx
          password: xxx
        slave:
          driver-class-name: org.postgresql.Driver
          url: jdbc:postgresql://host:port/twd?currentSchema="ruoyi-vue-pro"
          username: xxx
          password: xxx
          druid:
            validation-query: SELECT 1
            test-while-idle: true
            test-on-borrow: true
            test-on-return: false
            pool-prepared-statements: false

经验总结

  1. Schema 名称包含特殊字符(如连字符 -、空格等)时,必须用双引号包裹,否则在 GaussDB/OpenGauss 的连接池代理层会解析失败。

  2. 排查此类问题的有效方法:

    • 先用原生 JDBC DriverManager.getConnection 验证连接是否正常
    • 再用简单 SELECT 1 和 PreparedStatement 分别测试,定位问题层级
    • 对比能用的项目和不能用的项目的配置差异,重点看 URL 参数
  3. 使用 dynamic-datasource 多数据源时,必须排除 DruidDataSourceAutoConfigure,否则会导致数据源初始化冲突。

  4. GaussDB DWS 连接注意事项:

    • Schema 名称含特殊字符必须加双引号
    • 不要使用 useSSL=true(连接池代理通常不支持)
    • 不要开启 pool-prepared-statements
    • validation-query 使用 SELECT 1,不要加 FROM DUAL

相关错误对照表

错误信息 可能原因
pooler: failed to send set X handles Schema 名称含特殊字符未加引号;或 PgBouncer 为 transaction 模式
Read timed out 连接空闲超时被服务端断开;或 socketTimeout 设置过小
oid type true not known Druid 版本与 postgresql 驱动版本不兼容
keepAliveBetweenTimeMillis must be greater than timeBetweenEvictionRunsMillis keepAlive 时间需大于 timeBetweenEvictionRunsMillis
相关推荐
AI开源软件1 天前
SpringBoot信创项目怎么验收?从数据库迁移到交付证据
postgresql·springboot·达梦·opengauss·信创·企业管理系统
咖啡八杯2 天前
Redis 工具封装:RedisCache 对 Operations 体系的二次封装
java·数据库·redis·缓存·框架·springboot·若依
hyunbar2 天前
华为云 GaussDB(DWS) 和 PG 的谓词下推有何差异
华为云·gaussdb·dws
西凉的悲伤5 天前
Spring Boot 条件装配注解详解
java·springboot·1024程序员节·条件装配
xieliyu.6 天前
【JavaEE进阶】Spring Boot 日志:从 System.out 到 @Slf4j,6 个级别 + 4 类配置一篇讲透
java·spring boot·spring·java-ee·springboot·logback·slf4j
AI开源软件6 天前
SpringBoot + Vue3 人力资源管理系统推荐:组织、档案与移动办公
vue3·springboot·ruoyi·oa系统·移动办公·人力资源管理系统·hrm
AI源码6 天前
社区医院儿童健康信息管理系统
springboot
Gauss松鼠会7 天前
GaussDB 内存相关参数及故障诊断
运维·数据库·sql·oracle·性能优化·架构·gaussdb
AI源码7 天前
社区论坛系统
springboot
AI源码7 天前
图书馆借阅管理系统
vue3·springboot