通常の列に加えて、Postgresテーブルにはさまざまな システム列 も用意されています。それらの1つであるxmin
は、行の作成に使用されるトランザクションIDを格納します。そのデータ型はxid
であり、ある時点でラップアラウンドする4バイトの整数です(つまり、必ずしも一意である必要はありません)。関数txid_current()
は、現在のトランザクションIDを返しますが、bigint
として返されます。これは、「エポック」カウンターで拡張されているため、インストールの存続期間中にラップアラウンドしないためです。 ( manual を引用します)。
トランザクションの折り返しがまだ発生していない場合、両方の値は一致しているように見えます。
_# CREATE TABLE test (label text);
CREATE TABLE
# INSERT INTO test VALUES ('test') RETURNING txid_current();
txid_current
--------------
674500
(1 row)
INSERT 0 1
# SELECT xmin FROM test;
xmin
--------
674500
(1 row)
_
しかし、私は疑問に思います:これらの2つの値は常に比較可能ですか?私が理解している限り、txid_current()
はトランザクションIDの循環(最大2 ^ 32トランザクション)後も一意の値を提供し続け、xmin
はゼロから始まります。つまり、その時点で両方が異なる値を返し始めますか?
これがtrueの場合、txid_current()
結果の通常のxid
を抽出して、テーブルのxmin
エントリと一致するようにする方法があります(例:txid_current()
から整数へ)?
編集:2 ^ 32トランザクションよりもずっと前に発生する可能性が高いトランザクションIDラップアラウンド後に何が起きるかに注意することを明確にします。コメントでこれを指摘してくれたDanielVéritéに感謝します。
追加したエポックを取り除いて、xmin
の値と一致させることができます。つまり、integer
から4バイトのbigint
を抽出します。 xmin
はタイプxid
であり、(符号付き!)integer
ではないため、代わりにtext
表現を比較します。
SELECT * FROM test
WHERE xmin::text = (txid_current() % (2^32)::bigint)::text;
詳細な説明: