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
相关推荐
Gauss松鼠会2 天前
【GaussDB】GaussDB锁阻塞源头查询
java·开发语言·前端·数据库·算法·gaussdb·经验总结
xuekai200809012 天前
GaussDB 单机安装记录
gaussdb
周航宇JoeZhou2 天前
JP3-2-1-MyItem项目简介
java·ai·springboot·环境搭建·项目·管理·springai
剧号2 天前
互联网大厂Java面试全解析:Java SE 11, Spring Boot及微服务实战问答
java·微服务·面试·kafka·kubernetes·springboot·分布式系统
勿忘初心12213 天前
【Windows流媒体实战2】SpringBoot2.x 整合FFmpeg 完整实操教程
ffmpeg·springboot·流媒体开发·nginx-rtmp·rtmp视频录制
X-⃢_⃢-X4 天前
四、OpenFeign远程调用
java·微服务·springboot·springcloud
凤山老林5 天前
SpringBoot实战:构建优雅的全局异常处理机制
java·springboot·异常处理
长谷深风1115 天前
Java基础知识梳理(四):异常体系、finally与统一异常处理
springboot·异常处理·java基础·项目·统一异常处理·异常·finally机制
troyzhxu7 天前
列表查询的 GraphQL —— 一行代码终结你的 if-else 地狱!
java·springboot·graphql
极光代码工作室8 天前
基于SpringBoot的在线博客系统
java·springboot·web开发·后端开发