web-dev-qa-db-ja.com

PostgreSQLエラー:リカバリと競合するためステートメントをキャンセルします

スタンバイモードでPostgreSQL dbでクエリを実行すると、次のエラーが表示されます。エラーの原因となるクエリは1か月間は正常に機能しますが、1か月を超えるクエリを実行するとエラーが発生します。

ERROR: canceling statement due to conflict with recovery
Detail: User query might have needed to see row versions that must be removed

解決方法に関する提案はありますか?ありがとう

106
AnApprentice

ホットスタンバイサーバーでクエリを実行するのはやや注意が必要です。クエリ中に必要な行がプライマリで更新または削除される可能性があるため、失敗する可能性があります。プライマリは、クエリがセカンダリで開始されたことを知らないため、その行の古いバージョンをクリーンアップ(バキューム)できると考えています。次に、セカンダリはこのクリーンアップを再生する必要があり、これらの行を使用できるすべてのクエリを強制的にキャンセルする必要があります。

長いクエリはより頻繁にキャンセルされます。

これを回避するには、プライマリで反復可能な読み取りトランザクションを開始します。これは、ダミークエリを実行し、セカンダリで実際のクエリが実行されている間アイドル状態になります。その存在は、プライマリの古い行バージョンのバキュームを防ぎます。

この主題および他の回避策の詳細は、ドキュメントの ホットスタンバイ—クエリの競合の処理 セクションで説明されています。

72
Tometzky

マスターでアイドルトランザクションを開始する必要はありません。 postgresql-9.1でこの問題を解決する最も直接的な方法は、

hot_standby_feedback = on

これにより、マスターは長時間実行されるクエリを認識します。 docs から:

最初のオプションは、パラメータhot_standby_feedbackを設定することです。これにより、VACUUMが最近死んだ行を削除しないようにし、クリーンアップの競合が発生しないようにします。

なぜこれがデフォルトではないのですか?このパラメーターは初期実装後に追加されたもので、スタンバイがマスターに影響を与えることができる唯一の方法です。

71
eradman

hot_standby_feedbackに触れる必要はありません。他の人が述べたように、onに設定すると、マスターが膨張する可能性があります。スレーブでトランザクションを開き、閉じないことを想像してください。

代わりに、max_standby_archive_delayおよびmax_standby_streaming_delayを適切な値に設定します。

# /etc/postgresql/10/main/postgresql.conf on a slave
max_standby_archive_delay = 900s
max_standby_streaming_delay = 900s

この方法では、900秒未満の期間のスレーブに対するクエリはキャンセルされません。ワークロードでより長いクエリが必要な場合は、これらのオプションをより高い値に設定するだけです。

62
Max Malysh

述べたように ここhot_standby_feedback = onについて:

まあ、それの欠点は、スタンバイがマスターを肥大化させる可能性があることです。これは一部の人にとっても驚くべきことです

そして ここ

Max_standby_streaming_delayの設定は何ですか?むしろ、hot_standby_feedbackをデフォルトでオンにするよりもデフォルトで-1にしたいです。そのようにして、スタンバイで行うことはスタンバイにのみ影響します


だから私は追加しました

max_standby_streaming_delay = -1

そして、pg_dumpエラーはもうありません。

AWS RDSインスタンスの場合、 http://docs.aws.Amazon.com/AmazonRDS/latest/UserGuide/Appendix.PostgreSQL.CommonDBATasks.html を確認します

47
Gilles Quenot

ホットスタンバイスレーブサーバーのテーブルデータは、長時間実行されているクエリの実行中に変更されます。テーブルデータが変更されていないことを確認するソリューション(PostgreSQL 9.1以降)は、レプリケーションを中断し、クエリの後に再開することです。

select pg_xlog_replay_pause(); -- suspend
select * from foo; -- your query
select pg_xlog_replay_resume(); --resume
9
David Jaspers