Postgresの自動インクリメントPKによる順序付けは、作成の観点から、レコードを時系列で順序付けすると想定しても安全ですか?私には多対多の関係があり、そこから、関係自体と何らかの形の作成の順序以外は何も追跡する必要はありません。これにタイムスタンプ列を組み込む必要があるかどうか、または同じ目的で既存の自動インクリメントPK列を再利用できるかどうかを判断しようとしています。
「自動インクリメント」とは、Postgres SERIAL
疑似タイプ を意味すると仮定すると、簡単な答えは「常にではない」です。
SERIAL
列は、標準のSQLシーケンスを使用して実装されます。CACHE
パラメータが1より大きい値に設定されている場合、複数の同時セッションで使用すると、順序が乱れる可能性があります。 マニュアル状態 これ:
[A]複数のセッションが個別のシーケンス値を割り当てることが保証されていますが、すべてのセッションが考慮されると、値がシーケンスから生成される場合があります。たとえば、cache設定が10の場合、セッションAは値1..10を予約し、
nextval=1
を返すと、セッションBは値11..20を予約し、セッションAがnextval=11
を生成する前にnextval=2
を返す場合があります。したがって、cache設定が1の場合、nextval
値は順次生成されます。 cache設定が1より大きい場合は、nextval
値が完全に連続して生成されるのではなく、すべてが異なる。
CACHE
の値を1のままにしておくと、同時実行性の高い環境でパフォーマンスが低下する可能性があるため、より重要なものを選択する必要があります。
私の見解では、レコードの作成順序を追跡するためにSERIAL
を転用しようとすることは、メンテナンスの問題を引き起こす可能性があるため、良い考えではありません。シーケンスの唯一の約束は、各nextval
リクエストに対する一意の増分値、ある状況下でのその動作に依存すると、状況が変化したときにアプリケーションが予期しない動作をする可能性があります。たとえば、シーケンス実装の詳細は、将来のPostgresバージョンで変更されるか、ワークロードの変更により、CACHE
設定を増やす必要があります。順序付けに適切なタイムスタンプを使用すると、安全かつ意味的に明確になります。
時系列でどういう意味ですか?
トランザクション2の前に開始し、トランザクション2の後に終了するトランザクション1がある場合、最初のトランザクションはトランザクション1ですか、それともトランザクション2ですか?
SERIALIZABLE
トランザクション分離レベルを使用している場合は、トランザクションの合計順序が保証されます。つまり、トランザクションにシリアル(非パラレル)順序があり、同じ結果が得られます。実際の並列システムで実行されているトランザクション。
ほとんどの場合、PostgreSQLシーケンスは、シリアライズ可能な合計順序とまったく同じ値の順序を値に与えません。これを修正するには、独自のシーケンスを作成します。1つの整数列を持つ1つの行を持つテーブルを作成し、その行を更新します。ただし、これを行うと、トランザクションの並列性が低下します。トランザクションの一部が失敗するような方法でさえ影響を受ける可能性があります。
コメントで提案されている1つの解決策は、タイムスタンプです。ただし、タイムスタンプの順序は、同じ結果が得られるシリアルの順序と必ずしも同じではありません。
(補足として、すべての場合で失敗したトランザクションに備える必要があります。デッドロックは失敗したトランザクションを引き起こします。SERIALIZABLE
分離レベルはさらに失敗したトランザクションを引き起こします。適切な方法は、指数バックオフと再試行を行うことです。 )