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 参数(去掉 useSSLreWriteBatchedInserts 等)
  • 降级 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 1PreparedStatement 分别测试,定位问题层级
    • 对比能用的项目和不能用的项目的配置差异,重点看 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
相关推荐
她说..2 天前
MySQL 与 Java 的 JSON 数据处理
java·mysql·json·springboot
Mr.Java.3 天前
本地测试全绿,上线 SQL 报错?Spring Boot 容器级 DT 测试实战指南(附Skills)
java·测试用例·springboot·testcontainers·dt·java测试skills·dt测试
苏渡苇3 天前
Spring Insight 里上报 Span 为什么用 JDK HttpClient 而不是 RestTemplate
java·后端·spring·spring cloud·springboot·性能监控
欢醉3 天前
生产复盘:请求报413 Request Entity Too Large问题分享
springboot·springcloud
慧都小项5 天前
MyEclipse 2026:当 Agent、MCP 与 Java 26 进入 Eclipse 工作流
java·eclipse·springboot·copilot·myeclipse
冬栈程序设计6 天前
Springboot宿舍管理系统【670099】 -附源码(开箱即用)
java·毕业设计·springboot·课程设计·程序设计·大作业
Gauss松鼠会6 天前
【GaussDB】GaussDB 组件、节点和AZ故障仲裁与切换流程
运维·服务器·数据库·gaussdb
苏生Susheng7 天前
【软件实施】Linux企业运维常用命令手册
java·linux·运维·服务器·springboot·springcloud·软件实施
武哥聊编程7 天前
【AI实战项目】基于LangChain4j+Springboot+Vue+RAG+PGVector的AI智能客服与工单处理系统
springboot·rag·pgvector·langchain4j
小宇宙清歡渡7 天前
Java Stream 流全面实战指南(Spring Boot 3 + JDK 17)
java·springboot·stream流