java - Postgres-错误 : prepared statement "S_1" already exists

标签 java postgresql jdbc pgbouncer

当通过 JDBC 对 pgbouncer 执行批量查询时,出现以下错误:

org.postgresql.util.PSQLException: ERROR: prepared statement "S_1" already exists

我在网上找到了错误报告,但它们似乎都针对 Postgres 8.3 或更低版本,而我们正在使用 Postgres 9。

这是触发错误的代码:

this.getJdbcTemplate().update("delete from xx where username = ?", username);

this.getJdbcTemplate().batchUpdate( "INSERT INTO xx(a, b, c, d, e) " + 
                "VALUES (?, ?, ?, ?, ?)", new BatchPreparedStatementSetter() {
    @Override
    public void setValues(PreparedStatement ps, int i) throws SQLException {
        ps.setString(1, value1);
        ps.setString(2, value2);
        ps.setString(3, value3);
        ps.setString(4, value4);
        ps.setBoolean(5, value5);
    }
    @Override
    public int getBatchSize() {
        return something();
    }
});

有人以前见过这个吗?

编辑 1:

这原来是一个 pgBouncer 问题,在使用 session 池 以外的任何东西时都会发生。我们使用的是事务池,它显然不支持准备好的语句。通过切换到 session 池,我们解决了这个问题。

不幸的是,这对我们的用例来说不是一个好的解决方案。我们对 pgBouncer 有两个不同的用途:我们系统的一部分进行批量更新,这作为准备好的语句是最有效的,另一部分需要非常快速连续的许多连接。由于 pgBouncer 不允许在session poolingtransaction pooling 之间来回切换,我们不得不在不同的端口上运行两个单独的实例来满足我们的需求。

编辑 2:

我遇到了 this link ,海报已经滚动了他自己的补丁。如果它被证明是安全有效的,我们目前正在考虑将其用于我们自己的用途。

最佳答案

在 JDBC 中禁用准备好的语句。 JDBC 的正确方法是添加“prepareThreshold=0”参数来连接字符串。

jdbc:postgresql://ip:port/db_name?prepareThreshold=0

关于java - Postgres-错误 : prepared statement "S_1" already exists,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/7611926/

相关文章:

java - 扩展 java.lang.String

sql - 我无法弄清楚 v_out 和 v_in 在 SQL 语句中的含义

java - 空 ResultSet 仍在评估为真,JDBC

java - 使用预准备语句的变量列名

Java多级菜单结构

java - 在 javadoc 中记录逻辑

php - PostgreSQL Laravel 不返回 id

php - PDO 与 Azure PostgreSQL 建立连接非常慢

java - sql server 的等效 jdbc 连接字符串

java - 使用不返回结果的方法是好事吗?