web-dev-qa-db-ja.com

org.postgresql.util.PSQLException:エラー:リカバリとの競合によりステートメントをキャンセルしています

現在、PostgreSQLスレーブノードを使用していますが、マスターノードでは発生しない問題が発生しています。ノード同期プロセスに関連しているようです。

完全なスタックトレース:

org.postgresql.util.PSQLException: ERROR: canceling statement due to conflict with recovery
  Detail: User query might have needed to see row versions that must be removed.
    at org.postgresql.core.v3.QueryExecutorImpl.receiveErrorResponse(QueryExecutorImpl.Java:2103)
    at org.postgresql.core.v3.QueryExecutorImpl.processResults(QueryExecutorImpl.Java:1836)
    at org.postgresql.core.v3.QueryExecutorImpl.execute(QueryExecutorImpl.Java:257)
    at org.postgresql.jdbc2.AbstractJdbc2Statement.execute(AbstractJdbc2Statement.Java:512)
    at org.postgresql.jdbc2.AbstractJdbc2Statement.executeWithFlags(AbstractJdbc2Statement.Java:388)
    at org.postgresql.jdbc2.AbstractJdbc2Statement.executeQuery(AbstractJdbc2Statement.Java:273)
    at org.Apache.Tomcat.dbcp.dbcp2.DelegatingPreparedStatement.executeQuery(DelegatingPreparedStatement.Java:82)
    at org.Apache.Tomcat.dbcp.dbcp2.DelegatingPreparedStatement.executeQuery(DelegatingPreparedStatement.Java:82)
    at cl.waypoint.mailer.reportes.BasicReport.getSingleColumn(BasicReport.Java:542)
    at cl.waypoint.mailer.reportes.BasicReport.getSingleColumn(BasicReport.Java:518)
    at cl.waypoint.mailer.reportes.StatusSemanalClientes.updateIgnicion(StatusSemanalClientes.Java:448)
    at cl.waypoint.mailer.reportes.StatusSemanalClientes.access$2(StatusSemanalClientes.Java:447)
    at cl.waypoint.mailer.reportes.StatusSemanalClientes$TempAndDoorLocator.call(StatusSemanalClientes.Java:414)
    at cl.waypoint.mailer.reportes.StatusSemanalClientes$TempAndDoorLocator.call(StatusSemanalClientes.Java:1)
    at Java.util.concurrent.FutureTask$Sync.innerRun(FutureTask.Java:334)
    at Java.util.concurrent.FutureTask.run(FutureTask.Java:166)
    at Java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.Java:1110)
    at Java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.Java:603)
    at Java.lang.Thread.run(Thread.Java:722)

DBバージョン:

PostgreSQL 9.4.9 on x86_64-unknown-linux-gnu, compiled by gcc (Debian 4.9.2-10) 4.9.2, 64-bit

OSバージョン:

Distributor ID: Debian
Description:    Debian GNU/Linux 8.6 (jessie)
Release:    8.6
Codename:   jessie

問題は、問題の実際の原因をデバッグしたり、解決したり、回避したりするにはどうすればよいですか?問題を特定する必要がある場合は、遠慮なく詳細情報を要求してください。現在、他に何を提供すべきかわからないだけです。

PS:問題のあるクエリが繰り返されてもエラーは表示されないため、クエリ自体とは厳密には関係ありませんが、おそらくテーブルの更新/同期の一時的なものです。

2
Gonzalo Vasquez

マスターでスタンバイとより大きなクエリを実行しているすべての人に共通する経験です。いくつかあります 考えられる原因

ホットスタンバイで発生する可能性のある追加のタイプの競合もあります。これらの競合は、クエリをキャンセルする必要があり、場合によってはセッションを切断して解決するという意味で、激しい競合です。ユーザーには、これらの競合を処理するいくつかの方法が提供されています。競合のケースは次のとおりです。

明示的なLOCKコマンドとさまざまなDDLアクションの両方を含む、プライマリサーバーで行われるアクセス排他ロックは、スタンバイクエリのテーブルアクセスと競合します。

  • プライマリでテーブルスペースを削除すると、一時作業ファイル用にそのテーブルスペースを使用するスタンバイクエリと競合します。
  • プライマリでデータベースを削除すると、スタンバイでそのデータベースに接続されているセッションと競合します。
  • WALからのバキュームクリーンアップレコードの適用は、削除される行をスナップショットが「見る」ことができるスタンバイトランザクションと競合します。
  • WALからのバキュームクリーンアップレコードの適用は、削除するデータが表示されているかどうかに関係なく、スタンバイのターゲットページにアクセスするクエリと競合します。

上記のいずれかの理由でクエリが強制終了される時期を予測することは困難ですが、通常、より頻繁に表示されるものがあります。オプションについては、さらにドキュメントページを参照してください。

最も重要なオプションは hot_standby_feedback 、これは最も一般的な原因(VACUUM最近死んだ行を削除する)に役立ちます。独自のコストがあります(テーブルが肥大化する可能性があります)が、通常、マスターで同じクエリを実行するよりも結果は良好です。

4
dezso

同じことを2、3回経験しました。マスターに書き込み、読み取りはスレーブからでした。上記のエラーは、スレーブから読み取ったときに表示され始めましたが、同時に、機能上の制約のために他のプロセスがそのデータを削除しました。そのため、このような問題を解決するために、独自の「read your own writes」メソッドを追加しました。この方法では、アプリケーションスレッドがdbに書き込まれたばかりの内容を読み取る必要があります。その場合、マスターに書き込む特定のスレッドはマスターから読み取ります。はい、これとは逆に、読み取りのスケーラビリティには若干の妥協点があります。すべての読み取りをスレーブ(スタンバイ)に移動しましたが、トランザクションがデータを変更しないことが確認されました。トランザクションの分離レベルを繰り返し可能な読み取りに変更するなど、より複雑な回避策がありますが、アプリケーションコードは複雑になり、保守が難しくなります。 HTH。

0
Raghu Sastry