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

3
由于PostgreSQL文档 https://www.postgresql.org/docs/current/ddl-system-columns.html
"xmin"是插入此行版本的事务ID(行版本是一行的个别状态;每次更新行都会为同一逻辑行创建一个新的行版本)。
我们将其用于与PostgreSQL源数据库同步数据和提取(ETL中的E)更改,我们使用间隔扫描,特别是xmin间隔。例如,我们已同步了从0到10002的xmin间隔,并且在下一次同步时,我们将从10003开始搜索xmin。如果每个提交并可见的事务按顺序编号,则没有问题,所有数据更改将按顺序编号,但是如果事务在初始化时编号,则可能发生以下情况:
- 事务10001于15:01开始 - 事务10002于15:02开始 - 事务10002于15:02提交 - 事务10001于15:03提交
如果我们在15:02进行了同步,并且在目标数据库中获得了最大的xmin:在这种情况下是10002,在下一次从xmin 10003开始的同步中,我们将跳过xmin 10001并且会丢失更改。
那么PostgreSQL事务ID(xmin)是否按顺序出现在提交的版本中?

同一文档中也有xmax:

xmax 删除事务的标识(事务ID),或者对于未删除的行版本为零。这一列可能在可见的行版本中非零。这通常表示删除事务尚未提交,或者删除操作被回滚。

因此,我们可以看到计划删除行的事务(如果它将被提交),那么xmin是否也显示将更改行的事务?但是由于xmin的描述,这不可能是真的:

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

因为根据所写内容,它必须与我们读取的行版本匹配,这只能通过脏读(当我们看到未提交的数据时)来实现,但在PostgreSQL中无法发生https://www.postgresql.org/docs/current/transaction-iso.html

脏读:允许,但在PG中不允许。

2个回答

0

在撰写这个问题的过程中,我发现了这些幻灯片:https://momjian.us/main/writings/pgsql/mvcc.pdf,由于其中的“MVCC快照时间线”部分,我认为快照中xmin的出现可能不是按顺序的。

但我在这里找到了解决方案:https://www.postgresql.org/docs/9.6/functions-info.html#FUNCTIONS-TXID-SNAPSHOT

txid_snapshot_xip(txid_snapshot) [setof bigint] 获取快照中正在进行的事务ID

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


0

你的想法很好(除了你应该将txid_snapshot_xmin作为截止点),但它有两个缺点:

  • 事务ID是从4字节无符号整数计数器生成的,它会在某个时刻回绕。然后比较xmin将不再起作用。

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

所以我认为这种可爱的技巧注定要失败。

你应该研究一下逻辑解码,特别是wal2json插件。这将允许你可靠地捕获所有数据的更改。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接