【问题标题】:Does PostgreSQL transaction id (xmin) appears in committed version sequentially?PostgreSQL 事务 id (xmin) 是否按顺序出现在提交版本中?
【发布时间】:2020-05-28 01:55:29
【问题描述】:

由于 PostgreSQL 文档https://www.postgresql.org/docs/current/ddl-system-columns.html

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 中获得了 max 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 中不允许

【问题讨论】:

    标签: postgresql transactions mvcc


    【解决方案1】:

    在写这个问题的过程中,我发现了这张幻灯片: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 的 xid,如果包含则需要等待一段时间,然后再次检查并继续如果同步间隔内的所有事务都已完成,则提取数据,否则退出进程并出错。

    【讨论】:

      【解决方案2】:

      你的想法很好(除了你应该把txid_snapshot_xmin作为一个分界点),但它有两个缺点:

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

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

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

      您应该查看logical decoding,尤其是wal2json 插件。这将使您能够可靠地捕获对数据的所有更改。

      【讨论】:

        猜你喜欢
        • 2017-02-02
        • 1970-01-01
        • 1970-01-01
        • 2021-03-30
        • 2018-08-15
        • 2013-06-28
        • 2016-02-13
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多