有没有办法在 Postgres 中获取事务提交时间戳?

bsi*_*nau 8 postgresql timestamp

我有数据拉取功能,可以在 5 秒内根据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_timestamp变为 之后CURRENT_TIMESTAMP)。它工作正常,直到我注意到CURRENT_TIMESTAMPPostgres 实际上是事务开始时间戳并且一些更新丢失了。他们为什么会迷路?这很简单 - 在我执行查询时,SELECT * FROM my_table WHERE modified_timestamp > _some_persisted_timestamp一些更改已经发生,但modified_timestamp在更新_some_persisted_timestamp之前,因为事务仍在进行中。

当更新对其他事务可见(换句话说,事务提交时间戳)而不是 CURRENT_TIMESTAMP 或 clock_timestamp()时,可以通过在步骤 2 中 分配时间戳来轻松解决此问题。

我阅读了文档,但没有发现与事务提交时间戳相关的任何内容。你能不能给点建议?

顺便说一句,我知道逻辑解码,我知道这种机制在理论上更适合我的需求,但有一些实际问题不允许我使用它。

Erw*_*ter 9

当更新对其他事务可见(换句话说,事务提交时间戳)而不是 CURRENT_TIMESTAMP 或 clock_timestamp() 时,可以通过在步骤 2 中分配时间戳来轻松解决此问题。

这在逻辑上是不可能的。Postgres它最终提交以使其可见之前写入新的行版本。它需要预言能力来编写在编写时未知的未来时间戳。

但是,您可以从不同的来源获取提交时间戳:从 Postgres 9.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;
Run Code Online (Sandbox Code Playgroud)

请注意,提交时间戳不会永远保留。在 20 亿笔交易(2^31)之后,交易 ID 被“冻结”。这不会立即删除它,但是在 40 亿次交易之后,这些信息肯定会消失。这是大量的事务,只有非常繁忙的数据库才能在一生中消耗这么多。但是编程错误可能比预期的更快地烧毁交易编号......

您的第 2 步第 3 步交易头寸,您记录提交时间戳而不是CURRENT_TIMESTAMP- 或xmin从任何新更新的行中再次派生提交时间戳pg_xact_commit_timestamp()

更多的:

关于xmin

但我不完全确定我理解你的任务。也许您需要一个排队工具或像这里讨论的那样逐行处理: