【问题标题】:Implementing incremental client updates with rowversions in Postgres在 Postgres 中使用 rowversions 实现增量客户端更新
【发布时间】:2015-04-11 05:57:43
【问题描述】:

我是 Postgres 的新手,到目前为止我很喜欢它。我已经对这个问题进行了很多思考,尽我所能的 RTFM,但是走到了死胡同,所以我需要朝着正确的方向轻推。

我正在设计一个数据库,其中每个感兴趣的实体都有一个 rowversion 列,该列从全局序列中分配一个值。所以,在最简单的情况下,在一个有两行的表emps 中:emp1rowversion@3emp2rowversion@5,我知道emp2emp1 之后被修改(即在以后的事务中- 不介意同一事务中的行是否具有相同的rowversion)。

这是数据同步逻辑的基础,在该逻辑中,知道自己拥有直到@3 的所有内容的客户端可以使用诸如SELECT * FROM emps WHERE rowversion>3 and rowversion<=new_anchor 之类的查询来获取最新更新。

这是一个客户端已经更新的示例场景@3 - 假设以下事务:

@3 - committed
@4 - committed
@5 - committed
@6 - in progress - not committed yet
@7 - committed
@8 - in progress - not committed yet
@9 - committed

客户端更新分三个阶段进行:

  1. 向数据库询问适当的new_anchor
  2. 执行SELECT * FROM emps WHERE rowversion>3 and rowversion<=new_anchor
  3. new_anchor 值连同结果数据一起传回客户端。

由于rowversion@6 和@8 的行仍在进行中,new_anchor 必须为@5,这样我们的范围查询就不会错过任何未提交的更新。现在客户可以确信它拥有直到@5 的所有内容。

因此,实际问题得到了提炼:如何在不强制 SERIALIZABLE 或以其他方式严重损害性能的情况下安全地确定 new_anchor

您可能知道我从 SQL Server 借用了这个想法,min_active_rowversion() 函数轻松解决了这个问题。在上述情况下,此函数将返回@6,因此您的new_anchor 可以安全地为min_active_rowversion() - 1。我有点知道如何在 Postgres 中使用active_rowversions 表、触发器和SELECT min(id) FROM active_rowversions 来实现这一点,但这需要READ UNCOMMITTED 隔离,这在 Postgres 中不可用。

如果有任何帮助或想法,我将不胜感激。

【问题讨论】:

    标签: sql sql-server database postgresql


    【解决方案1】:

    感谢 Postgres 的System Information Functions,解决方案比最初想象的要简单得多。

    • txid_current() 可在触发器中用于分配记录的rowversion
    • txid_snapshot_min(txid_current_snapshot()) 可用于获取最小活动事务,方法与 SQL Server 用户可能使用 min_active_rowversion() 的方式相同。

    最好的部分是这些是 64 位的、永久的、不受真空吸尘器的影响:

    这些函数导出 64 位格式,该格式使用“纪元”计数器进行扩展,因此在安装的生命周期内不会回绕。

    Postgres 真的很棒。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2021-10-26
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多