28

JDBC 経由で pgbouncer にバッチ クエリを実行すると、次のエラーが発生します。

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

Web でバグ レポートを見つけましたが、それらはすべて 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 には 2 つの用途があります。システムの 1 つの部分は、プリペアド ステートメントとして最も効率的な一括更新を行い、別の部分は非常に迅速に連続して多数の接続を必要とします。pgBouncer では、セッション プーリングトランザクション プーリングを切り替えることができないため、ニーズをサポートするためだけに、異なるポートで 2 つの個別のインスタンスを実行する必要があります。

編集2:

私はこのリンクに出くわしました , ポスターは彼自身のパッチを転がしました. 現在、安全で効果的であることが証明された場合、私たち自身の使用のためにそれを実装することを検討しています.

4

5 に答える 5

5

新しい、より良い答え

セッション状態を破棄し、「S_1」準備済みステートメントを効果的に忘れるには、PgBouncer 構成で server_reset_query オプションを使用します。

古い回答

http://pgbouncer.projects.postgresql.org/doc/faq.html#_how_to_use_prepared_statements_with_transaction_poolingを参照してください。

セッション モードへの切り替えは、理想的なソリューションではありません。トランザクション プーリングははるかに効率的です。ただし、トランザクション プーリングには、ステートレス DB 呼び出しが必要です。

次の 3 つのオプションがあると思います。

  1. jdbc ドライバーで PS を無効にします。
  2. Java コードでそれらを手動で割り当て解除し、
  3. トランザクション終了時にそれらを破棄するように pgbouncer を設定します。

アプリがそれらを使用する実際の方法に応じて、オプション 1 またはオプション 3 を試してみます。

詳細については、次のドキュメントを参照してください。

http://pgbouncer.projects.postgresql.org/doc/config.html (server_reset_query を検索)、

またはこれについてグーグル:

postgresql jdbc +preparethreshold
于 2011-10-03T22:41:45.693 に答える
3

これは、セッション プーリング以外のものを使用しているときに発生する pgBouncer の問題であることが判明しました。明らかに準備されたステートメントをサポートできないトランザクションプーリングを使用していました。セッション プーリングに切り替えることで、この問題を回避しました。

残念ながら、これは私たちのユースケースには適した修正ではありません。pgBouncer には 2 つの用途があります。システムの 1 つの部分は、プリペアド ステートメントとして最も効率的な一括更新を行います。もう 1 つの部分は、非常に迅速に連続して多くの接続を必要とします。pgBouncer ではセッション プーリングトランザクション プーリングを切り替えることができないため、ニーズをサポートするためだけに異なるポートで 2 つの個別のインスタンスを実行するか、このパッチを実装する必要があります。予備試験ではうまく機能することが示されていますが、安全で効果的であることが証明されるかどうかは時間が経てばわかります.

于 2011-09-30T15:25:52.860 に答える
0

私はこの問題を抱えていました。pgbouncer をトランザクション レベルで構成しました。psql 11.8 を使用していました。psql jar を最新バージョンにアップグレードしたところ、修正されました。

于 2020-07-01T06:06:44.893 に答える