web-dev-qa-db-ja.com

トランザクションIDのラップアラウンド後にxminとtxid_current()を比較する方法は?

通常の列に加えて、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éに感謝します。

12
tomka

追加したエポックを取り除いて、xminの値と一致させることができます。つまり、integerから4バイトのbigintを抽出します。 xminはタイプxidであり、(符号付き!)integerではないため、代わりにtext表現を比較します。

SELECT * FROM test
WHERE  xmin::text = (txid_current() % (2^32)::bigint)::text;

詳細な説明:

6