web-dev-qa-db-ja.com

Postgresでトランザクションコミットタイムスタンプを取得する方法はありますか?

5秒に1回、modified_timestamp列に基づいてPostgresテーブルからすべてのデータを取得するデータプル機能があります。次のように機能します。

  1. SELECT * FROM my_table WHERE modified_timestamp > _some_persisted_timestamp
  2. _some_persisted_timestamp = CURRENT_TIMESTAMP
  3. ステップ1から受け取ったデータの処理
  4. 5秒間スリープ
  5. ステップ1に進みます

modified_timestampがトリガーで更新された場所(行の更新後modified_timestampCURRENT_TIMESTAMP)。 CURRENT_TIMESTAMP Postgresは実際にはトランザクション開始のタイムスタンプであり、一部の更新が失われています。なぜ彼らは失われたのですか?それは非常に簡単です-クエリを実行する現時点ではSELECT * FROM my_table WHERE modified_timestamp > _some_persisted_timestamp一部の変更はすでに発生していますが、modified_timestampは更新される前です_ some_persisted_timestampトランザクションがまだ進行中であるため。

この問題は、step 2timestampを他のトランザクションで更新が表示されたときに割り当てることで簡単に解決できます(つまり、トランザクションコミットのタイムスタンプ)CURRENT_TIMESTAMPまたはclock_timestamp()の代わり。

ドキュメントを読みましたが、トランザクションコミットのタイムスタンプに関連するものは何も見つかりませんでした。あなたは親切に親切に提案してもらえますか?

ところで、私は 論理デコード を知っています。理論上、このメカニズムは私のニーズにより適していることを知っていますが、使用できない特定の実際的な問題があります。

4
bsiamionau

この問題は、ステップ2で、CURRENT_TIMESTAMPまたはclock_timestamp()の代わりに、他のトランザクション(トランザクションコミットのタイムスタンプ)の更新が表示されるときのタイムスタンプを割り当てることで簡単に解決できます。

これは論理的に不可能です。 Postgresは新しい行バージョンbeforeを書き込み、最終的にコミットしてそれらを可視にします。執筆時点では不明な将来のタイムスタンプを書き込むには、予言機能が必要です。

ただし、別のソースからコミットタイムスタンプを取得できます。Postgres9.5以降、GUC設定があります- _track_commit_timestamp_コミットタイムスタンプのグローバルなロギングを開始します。

次に、ユーティリティ関数 pg_xact_commit_timestamp(xid) でコミットタイムスタンプを取得できます。クエリは次のようになります。

_SELECT * FROM my_table t
WHERE   pg_xact_commit_timestamp(t.xmin) > _some_persisted_timestamp;
_

あなたのstep 2 andstep 3トレードポジション、そして_CURRENT_TIMESTAMP_-またはxminの代わりにコミットタイムスタンプを記録して、新しく更新された行からpg_xact_commit_timestamp()でコミットタイムスタンプをもう一度取得します。

もっと:

xminについて:

しかし、私はあなたの仕事を理解していることを完全には確信していません。たぶん、ここで説明したように、キューイングツールが必要か、行を1つずつ処理します。

6