Postgres - ОШИБКА: подготовленное заявление "S_1" уже существует - PullRequest
16 голосов
/ 30 сентября 2011

При выполнении пакетных запросов через 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 не позволяет переключаться между пулом сеансов и пулом транзакций , мы вынуждены запускать два отдельных экземпляра на разных портах только для удовлетворения наших потребностей.

Редактировать 2:

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

Ответы [ 2 ]

2 голосов
/ 04 октября 2011

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

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

Старый ответ

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

Переключение в режим сеанса не является идеальным решением. Транзионный пул гораздо эффективнее. Но для пула транзакций вам нужны вызовы БД без сохранения состояния.

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

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

Я бы попробовал вариант 1 или вариант 3 - в зависимости от того, каким образом ваше приложение использует их.

Для получения дополнительной информации прочитайте документы:

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

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

postgresql jdbc +preparethreshold
0 голосов
/ 30 сентября 2011

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

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

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...