我是Postgres的新手,到目前为止很喜欢它。我已经尽了最大的努力来考虑这个问题,RTFM已尽我所能,但是已经走到了尽头,因此我需要朝着正确的方向轻推。
我正在设计一个数据库,其中每个感兴趣的实体都有一个rowversion从全局序列中分配值的列。因此,在最简单的情况下,在emps具有两行的表中:emp1withrowversion@3和emp2with rowversion@5,我知道之后emp2进行了修改emp1(即在以后的事务中- 不必介意同一事务中的行是否具有相同的rowversion)。
rowversion
emps
emp1
rowversion@3
emp2
rowversion@5
这构成了 数据同步逻辑 的基础,在该 同步中 ,知道自己拥有@ 3之前的所有信息的客户端可以使用诸如之类的查询来获取最新更新SELECT * FROM emps WHERE rowversion>3 and rowversion<=new_anchor。
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
由于带有rowversion@ 6和@ 8的行仍在进行中,new_anchor因此必须为@ 5, 以便我们的范围查询不会丢失任何未提交的update 。现在,客户可以放心,直到@ 5为止,一切都可以满足。
因此,实际问题 得以 提炼: 如何new_anchor在不强迫SERIALIZABLE或严重损害性能的情况下安全地确定这一点?
SERIALIZABLE
如您所知,我是从SQL Server借用这个想法的,该问题通过该min_active_rowversion()函数可以轻松解决。在上述情况下,此函数将返回@ 6,因此您new_anchor可以放心地成为min_active_rowversion() - 1。我有点了解如何使用active_rowversions表,触发器和在Postgres中实现此功能SELECT min(id) FROM active_rowversions,但这需要READ UNCOMMITTED隔离,而Postgres中不提供隔离功能。
min_active_rowversion()
min_active_rowversion() - 1
active_rowversions
SELECT min(id) FROM active_rowversions
READ UNCOMMITTED
我真的很感谢任何帮助或想法。
事实证明,得益于Postgres的系统信息功能,该解决方案比最初想像的要简单得多。
txid_current()
txid_snapshot_min(txid_current_snapshot())
最好的部分是这些是64位的,永久的,不受清除的影响:
这些函数导出64位格式,该格式使用“ epoch”计数器扩展,因此在安装期间不会回绕。
Postgres确实很棒。