PostgreSQL事务id(xmin)是否按顺序出现在提交的版本中?

PostgreSQL事务id(xmin)是否按顺序出现在提交的版本中?,postgresql,transactions,mvcc,Postgresql,Transactions,Mvcc,由于PostgreSQL文档 xmin此行版本的插入事务的标识(事务ID)(行版本是行的单个状态;行的每次更新都会为同一逻辑行创建新的行版本) 我们使用它(不要问为什么,只是碰巧)来同步数据并从PostgreSQL源数据库中提取(ETL中的E)更改,我们使用间隔扫描,特别是xmin间隔,例如我们将xmin间隔从0同步到10002,在本例中,当我们进行下一次同步时,我们将从10003开始搜索xmin。如果已提交和可见的每个事务都按顺序编号,则没有问题,所有数据更改都将按顺序编号,但如果事务在初始化

由于PostgreSQL文档

xmin此行版本的插入事务的标识(事务ID)(行版本是行的单个状态;行的每次更新都会为同一逻辑行创建新的行版本)

我们使用它(不要问为什么,只是碰巧)来同步数据并从PostgreSQL源数据库中提取(ETL中的E)更改,我们使用间隔扫描,特别是xmin间隔,例如我们将xmin间隔从0同步到10002,在本例中,当我们进行下一次同步时,我们将从10003开始搜索xmin。如果已提交和可见的每个事务都按顺序编号,则没有问题,所有数据更改都将按顺序编号,但如果事务在初始化时编号,则可能发生下一种情况:

  • 事务处理10001于15:01开始
  • 事务处理10002于15:02开始
  • 交易10002于15:02提交
  • 交易10001于15:03提交
如果我们在15:02进行了同步,并且在目标DB:10002中获得了最大xmin,那么在从xmin10003开始的下一次同步中,我们将跳过xmin10001,并将丢失更改

那么PostgreSQL事务id(xmin)在提交的版本中是否按顺序显示?


同一单据中也有xmax:

xmax删除事务的标识(事务ID),或对于未删除的行版本为零。此列在可见行版本中可能不为零。这通常表示删除事务尚未提交,或者尝试的删除已回滚

所以我们可以看到计划删除行的事务(若它将被提交),所以xmin也可能显示将更改行的事务?但这不可能是真的,因为xmin描述:

…对于此行版本。(行版本是行的单个状态;行的每次更新都会为同一逻辑行创建新的行版本。)

因为,正如所写的,它必须与我们读取的行版本相匹配,可能只有脏读(当我们看到未提交的数据时)才能匹配,但这在PostgreSQL中不会发生

脏读:允许,但不在第页


在写这个问题的过程中,我发现了这张幻灯片:由于它的“MVCC快照时间线”部分,我认为快照中xmin的出现不可能是连续的

但我在这里找到了解决办法:

txid\u快照\u xip(txid\u快照)[setof bigint]在快照中获取正在进行的事务ID

因此,我可以获取尚未提交的事务集,并检查它们是否包含小于关闭当前同步进程间隔的最大xid的xid,如果包含,则需要等待一段时间,然后再次检查,如果同步间隔中的所有事务都已完成,则继续提取数据,否则将导致错误退出流程。

您的想法很好(除了您应该将
txid\u snapshot\u xmin
作为截止点),但它有两个缺点:

  • 事务ID是从一个4字节无符号整数计数器生成的,该计数器将在某个点环绕。然后比较
    xmin
    将不再有效

  • 为了避免这个问题,PostgreSQL将在某个时候在旧行上设置“冻结”标志,这在SQL中是不可见的。对于冻结行,必须忽略
    xmin
    xmax

所以我认为可爱的技巧是注定的

您应该仔细研究,尤其是插件。这将允许您可靠地捕获数据的所有更改