【发布时间】:2011-11-28 13:00:30
【问题描述】:
通过 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 问题。我们使用的是事务池,它显然不支持准备好的语句。通过切换到会话池,我们解决了这个问题。
很遗憾,这对我们的用例来说不是一个好的解决方案。我们对 pgBouncer 有两种不同的用途:我们系统的一部分进行批量更新,这作为准备好的语句最有效,另一部分需要非常快速的连续连接。由于 pgBouncer 不允许在 session pooling 和 transaction pooling 之间来回切换,我们不得不在不同的端口上运行两个单独的实例来满足我们的需求。
编辑 2:
我遇到了this link,发帖人已经在其中滚动了自己的补丁。如果它被证明是安全有效的,我们目前正在考虑实施它以供我们自己使用。
【问题讨论】:
-
可能是 pgbouncer 问题?还是过时的 JDBC 驱动程序?
-
绝对是 pgbouncer 的问题。我们绕过 pgbouncer 直接点击 Postgres,prepared 语句就可以工作了。 JDBC 驱动程序是最新可用的。
-
是否有一些设置告诉 pgbouncer 在释放回池时重置连接?听起来您正在重用之前已经运行过准备的连接。
-
@ScottMarlowe 有。这是连接池选项。我们使用
transaction pooling,它应该在事务结束后立即将连接释放回池。 -
这不是释放连接,而是重置它。如果它没有对连接进行重置,那么像准备好的查询这样的旧东西仍然可以存在。
标签: java postgresql jdbc pgbouncer