【发布时间】:2015-04-11 05:57:43
【问题描述】:
我是 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 的所有内容。
因此,实际问题得到了提炼:如何在不强制 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