You need to enable JavaScript to run this app.
最新活动
大模型
产品
解决方案
定价
生态与合作
支持与服务
开发者
了解我们

PostgreSQL JDBC单表扫描ResultSet行数为预期4倍的问题

排查Tomcat JDBC连接池返回ResultSet行数异常的问题

这种明明数据库里只有3行数据,代码里却拿到4倍结果的情况确实挺闹心的,我帮你梳理几个常见的排查方向和解决办法:

先确认核心信息是否一致

  • 把代码里执行的完整SQL语句打印出来,和你在pgAdmin里跑的做对比,确保没有差异——比如会不会代码里不小心写了重复的表关联(比如SELECT * FROM ref_table t1, ref_table t2),或者拼接SQL时多了循环导致重复?
  • 在遍历ResultSet的时候加个日志,打印每行的唯一标识(比如主键),看看是每行重复了4次,还是真的出现了额外的行——这能帮你定位是重复执行了查询,还是结果集本身有问题。

检查代码里的ResultSet处理逻辑

大概率是这里出了问题:

  • 有没有不小心在循环里重复添加元素?比如是不是写了嵌套循环,或者在rs.next()的循环里多次调用list.add()
  • 有没有重复执行查询语句?比如是不是在一个4次的循环里反复调用了executeQuery(),导致每次查询的3行都被加到列表里,最后凑成12行?
  • 之前用putIfAbsent能规避,说明返回的是重复数据,这更指向代码里重复获取了结果,或者连接池的配置导致重复执行。

排查Tomcat JDBC连接池的配置

打开你的context.xml(或者数据源配置文件),检查这几个关键参数:

  • defaultAutoCommit:如果设置为false,有没有在执行查询后手动提交?虽然查询一般不需要提交,但如果同一个连接被重复使用且没有重置,可能会出现异常;建议设置为true(默认值也是true)。
  • testOnBorrowvalidationQuery:如果配置了验证查询,会不会验证的结果和业务查询的结果混在了一起?不过这个概率比较低,但可以暂时把testOnBorrow设为false测试一下。
  • 连接池的maxIdleminIdle这些参数一般不会导致这个问题,但可以确认下有没有配置错误导致连接复用异常。

检查PostgreSQL驱动兼容性

Tomcat 9.0搭配PostgreSQL 10.2,要确保驱动版本是兼容的:

  • 建议使用PostgreSQL JDBC Driver 42.2.x系列(适配PostgreSQL 9.4到12),如果用的是太老的驱动(比如9.x系列),可能和Tomcat的连接池存在兼容性问题,导致ResultSet处理异常。
  • 替换驱动后再测试,看看问题是否消失。

做个最小化测试

写个简单的测试代码,绕过Tomcat连接池,直接用JDBC原生连接执行查询:

public static void main(String[] args) throws Exception {
    Class.forName("org.postgresql.Driver");
    Connection conn = DriverManager.getConnection("jdbc:postgresql://localhost:5432/yourdb", "user", "pass");
    Statement stmt = conn.createStatement();
    ResultSet rs = stmt.executeQuery("SELECT * FROM your_ref_table");
    int count = 0;
    while (rs.next()) {
        count++;
        System.out.println("Row " + count + ": " + rs.getString("your_unique_col"));
    }
    System.out.println("Total rows: " + count);
    rs.close();
    stmt.close();
    conn.close();
}

如果这个测试里行数正常(3行),那问题肯定出在Tomcat连接池的配置或者代码里的连接使用逻辑;如果还是异常,那就要检查数据库本身或者SQL的问题了。


内容的提问来源于stack exchange,提问作者dtgman

火山引擎 最新活动