Postgres-ERROR: подготовленный оператор "S 1" уже существует

при выполнении пакетных запросов через 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();
    }
});

кто-нибудь видел это раньше?

Edit 1:

это оказалось проблемой pgBouncer, которая возникает, когда используя ничего кроме сессии зачет. Мы использовали операции объединения, который, по-видимому, не может поддерживать подготовленные заявления. Переключившись на сессии зачет, мы обошли проблему.

к сожалению, это не хорошее решение для нашего случая использования. У нас есть два отдельных использования для pgBouncer: одна часть нашей системы делает массовые обновления, которые наиболее эффективны как подготовленные заявления, а другая часть нуждается во многих соединениях очень быстро преемственность. С pgBouncer не позволяет переключаться между сессии зачет и операции объединения, мы вынуждены запускать два отдельных экземпляра на разных портах только для поддержки наших потребностей.

Edit 2:

я наткнулся этой ссылке, где плакат свернул свою собственную заплату. В настоящее время мы рассматриваем его реализацию для наших собственных целей, если он окажется безопасным и эффективно.

2 ответов


Новый, Лучший Ответ

чтобы отбросить состояние сеанса и эффективно забыть "S_1" подготовленный оператор, используйте параметр server_reset_query в конфигурации PgBouncer.

Ответ

см http://pgbouncer.projects.postgresql.org/doc/faq.html#_how_to_use_prepared_statements_with_transaction_pooling

переключение в режим сеанса не является идеальным решением. Объединение Transacion является гораздо более эффективным. Но для объединяя операции БД без гражданства.

Я думаю, что у вас есть три варианта:

  1. отключить PS в драйвере jdbc,
  2. вручную освободить их в коде Java,
  3. настройте pgbouncer, чтобы отбросить их в конце транзакции.

Я бы попробовал вариант 1 или Вариант 3 - в зависимости от вашего приложения.

для получения дополнительной информации, читайте docs:

http://pgbouncer.projects.postgresql.org/doc/config.html (поиск server_reset_query),

или Google для этого:

postgresql jdbc +preparethreshold

Это оказалось проблемой pgBouncer, которая возникает при использовании чего-либо, кроме сессии зачет. Мы использовали операции объединения, который, по-видимому, не может поддерживать подготовленные заявления. Переключившись на сессии зачет, мы обошли проблему.

к сожалению, это не хорошее решение для нашего случая использования. У нас есть два отдельных использования для pgBouncer: одна часть нашей системы делает массовые обновления, которые наиболее эффективны, как подготовлены высказывания, а другая часть нуждается во многих связях в очень быстрой последовательности. С pgBouncer не позволяет переключаться между сессии зачет и операции объединения, мы вынуждены либо запускать два отдельных экземпляра на разных портах только для поддержки наших потребностей, либо реализовать этот патч. Предварительное тестирование показывает, что он работает хорошо, но время покажет, если он окажется безопасным и эффективным.