リピータブルリード分離レベルとシリアライザブル分離レベルはどちらも、直列化異常を防止するように設計されたエラーを生成する可能性があります。
前述のように、これらのレベルを使用するアプリケーションは、直列化エラーが原因で失敗したトランザクションを再試行するように準備する必要があります。
このようなエラーのメッセージ・テキストは細かい状況によって異なりますが、常にSQLSTATEコードは40001
(serialization_failure
)となります。
SQLSTATEコード40P01
(deadlock_detected
)を持つデッドロック障害を再試行することも推奨されます。
場合によっては、SQLSTATEコード23505
(unique_violation
)を持つ一意キーの失敗、およびSQLSTATEコード23P01
(exclusion_violation
)を持つ排他制約の失敗を再試行することも適切です。
たとえば、現在格納されているキーを検査した後にアプリケーションが主キー列に新しい値を選択した場合、別のアプリケーション・インスタンスが同じ新しいキーを同時に選択したため、一意キーの失敗が発生する可能性があります。
これは実質的に直列化の失敗ですが、サーバは挿入された値と前の読み取りとの間の関係を「参照」できないため、直列化の失敗を検出しません。
また、原則として直列化の問題が根本原因であると判断するのに十分な情報があるにもかかわらず、サーバーが一意キーまたは排他制約のエラーを発行する場合もあります。
serialization_failure
エラーを無条件に再試行することをお薦めしますが、これらの他のエラー・コードを再試行する場合は、一時的な失敗ではなく永続的なエラー条件を表す可能性があるため、より注意が必要です。
どのSQLを発行するか、どの値を使用するかを決定するすべてのロジックを含む完全なトランザクションを再試行することが重要です。 したがって、PostgreSQLは自動再試行機能を提供していません。 なぜなら、自動再試行機能は正当性を保証できないからです。
トランザクションの再試行は、再試行されたトランザクションが完了することを保証するものではありません。 複数回の再試行が必要になる場合があります。 競合が非常に高い場合は、トランザクションの完了に多くの試行が必要になる可能性があります。 競合する準備済トランザクションが関係する場合は、準備済トランザクションがコミットまたはロールバックされるまで進行できない可能性があります。