Aws RDSのpostgresqlマスタースレーブレプリケーション方式のレプリケーションサーバーで、次のエラーが発生します。
SQLSTATE[40001]: Serialization failure: 7 ERROR: canceling statement due to conflict with recovery
原因は、私が理解している限り、レプリケーションはデータベースの移行と同様に発生することです。クエリのシーケンスはWALと呼ばれるもので記述され、FIFOシーケンスで実行されます。
また、walの実行中にクエリを実行すると、競合が発生する可能性があることを理解しました。現在実行中のクエリが古いデータをフェッチする場合があるためです。
したがって documentation によると、まず現在のクエリを実行し、次にウォル変更を適用できる遅延があります。これらは次のとおりです。
max_standby_archive_delay
max_standby_streaming_delay
しかし、重いクエリ(クエリ実行時間> 30秒)でこれらの値を-1に設定すると、レプリカが長期間にわたって古いデータを持つことになりますか?
はい、それがアイデアです。レプリケーションの競合が発生した場合、PostgreSQLには2つのオプションしかありません。
クエリをキャンセルする
複製された変更の適用を遅らせます。
max_standby_streaming_delay
を-1に設定すると、レプリケーションが無期限に遅延します。
レプリケーションの競合を減らす方法はいくつかあります。
hot_standby_feedback = on
を設定して、VACUUM
によって引き起こされたレプリケーションの競合を削除します。 あなたが払っている価格は、スタンバイで長時間実行されているクエリがあなたのテーブルを膨らませることができるということです。
ワークロードにDROP TABLE
ロックを引き起こすALTER TABLE
、TRUNCATE
、ACCESS EXCLUSIVE
などのステートメントを含めないでください。
PostgreSQL v12では、次のように設定できます。
ALTER TABLE atable SET (vacuum_truncate = off);
自動バキュームの切り捨てを無効にします(これにより、短いACCESS EXCLUSIVE
ロックも発生します)。古いバージョンでは、old_snapshot_threshold
をデフォルト値以外の値に設定するという、文書化されていない大まかな回避策しかありません。
これはすべて複雑であり、望ましくない影響を与える可能性があるため、最良のアドバイスは次のとおりです:必要以上に遅れないスタンバイが必要であるが、スタンバイサーバーで長時間実行されるクエリも実行する場合、これらの競合する目的のそれぞれに1つずつ、2つのスタンバイサーバーを使用する必要があります。