我是Postgres的新人并且喜欢它到目前为止。我已经很多想到了这个问题,RTFM尽我所能,但是走到了尽头,所以我需要朝着正确的方向努力。
我正在设计一个数据库,其中每个感兴趣的实体都有一个rowversion
列,从全局序列中分配一个值。因此,在最简单的情况下,在包含两行的emps
表中:emp1
rowversion@3
和emp2
rowversion@5
,我知道emp2
在emp1
之后进行了修改(即在以后的交易中 - 如果同一交易中的行具有相同的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
客户端更新分三个阶段执行:
new_anchor
。SELECT * FROM emps WHERE rowversion>3 and rowversion<=new_anchor
。new_anchor
值与结果数据一起传递回客户端。由于rowversion
@ 6和@ 8的行仍在进行中,new_anchor
必须为@ 5,,以便我们的范围查询不会错过任何未提交的更新。现在,客户可以确信它拥有一切,直到@ 5。
因此,实际问题已被提炼出来:如何在不强制new_anchor
或严重损害绩效的情况下安全确定SERIALIZABLE
如何安全?
你可以告诉我,我已经从SQL Server借用了这个想法,这个问题可以通过min_active_rowversion()
函数轻松解决。在上面的场景中,此函数将返回@ 6,因此new_anchor
可以安全地min_active_rowversion() - 1
。我有点想知道如何使用active_rowversions
表,触发器和SELECT min(id) FROM active_rowversions
在Postgres中实现这一点,但这需要READ UNCOMMITTED
隔离,这在Postgres中是不可用的。< / p>
我真的很感激任何帮助或想法。
答案 0 :(得分:5)
事实证明,解决方案比最初想象的要简单得多,感谢Postgres'System Information Functions。
txid_current()
来分配记录rowversion
。txid_snapshot_min(txid_current_snapshot())
可用于以与SQL Server用户可能使用的min_active_rowversion()
相同的方式获取最小活动事务。最好的部分是64位,永久性,不受吸尘:
Postgres确实令人惊叹。这些函数导出64位格式,该格式使用“epoch”计数器进行扩展,因此在安装期间不会包裹。