Geir Bostad からの回答は正しいです。多くの場合、これについて理解するのに苦労するので、例と考えられる回避策を提供するためだけに回答しています。他の回答で参照されているWikiページに加えて、バッチが閉じられていると見なされているが、バッチの最終的な詳細をまだ表示できない「預金レポート」の例を含む、例のためだけの別のWikiページがあります。
ホット スタンバイは読み取り専用であるため、一時的なシリアライゼーションの異常しか確認できません。データは、最終的に後続のトランザクションで一貫した状態に落ち着きます。これは、プライマリ サーバーの反復可能な読み取りトランザクションで発生する可能性があるものと同じであり、プライマリ サーバーのシリアル化可能なトランザクションでは発生しません。混乱を避けるために、シリアライズ可能なトランザクションはホット スタンバイでは許可されていません。これは、真にシリアライズ可能なトランザクションの動作が (まだ) 保証されていないためです。DEFERRABLE
のオプションと同様に、異常が発生するリスクなしにシリアライズ可能なトランザクションを開始できるポイントを特定するために、WAL ストリームに情報を追加するという話がありましたSTART TRANSACTION
。これ (またはそれに似たもの) は、将来のバージョンで追加される可能性があります。
スナップショット分離を使用する読み取り専用トランザクション (Oracle または 9.1 より前のバージョンの PostgreSQL でシリアル化可能と識別されたトランザクションを含む) の場合、最も一般的なタイプの異常は、トランザクションに対して「クローズ」と表示される SELECT リストまたはバッチの要約であると思われます。バッチに含める必要があるすべての作業を表示せずに。これを確認するには、バッチを閉じるトランザクションは、バッチの詳細を変更するいくつかのトランザクションと「重複」(同時に実行) する必要があり、バッチを閉じるトランザクションは最初にコミットする必要があり、次に (バッチを閉じるトランザクションがコミットされた後、バッチの詳細を変更するトランザクションの前に)コミット) 読み取り専用トランザクションを開始し、そのスナップショットを取得する必要があります。
これを防ぐための最も簡単な方法は、プライマリで読み取りと書き込みの依存関係から書き込みと書き込みの競合に「競合を促進」することです。たとえば、上記の「預金レポート」の例では、deposit_total 列をコントロール テーブルに追加できます。コントロール テーブルは、deposit_no がインクリメントされたときに AFTER トリガーによってゼロに設定されます。また、AFTER トリガーをレシート テーブルに追加して、各レシートの金額に基づく金額。これにより、制御レコードの書き込み競合に基づいてシリアライゼーション エラーが発生し、異常がレプリカに伝播されなくなります。