我想创建一个Web服务,它允许客户端获取表中的所有行,然后稍后允许客户端仅获取新的或更新的行。仅向客户端发送更新的行
最简单的实现似乎是将当前时间戳发送到客户端,然后让客户端询问比以下请求中的时间戳更新的行。
看起来,通过在更新和插入触发器中保留“updated_at”列的时间戳设置为NOW(),然后查询更新的行并传递NOW()值,可行。
的问题是,如果有未提交的事务,这些事务将设置的updated_at到事务的开始时间,而不是提交时间。
因此,这个简单的实现不起作用,因为行可以丢失,因为它们可以在过去出现时间戳。
尽管这似乎是一个非常普遍的需求,但我一直无法找到任何简单的解决方案来解决这个问题:任何想法?
可能的解决方案:
保持单调时间戳在表中,在每一笔交易的开始到MAX更新(NOW(),last_timestamp + 1),并把它作为一个行时间戳。问题:这实际上意味着所有写入事务都是完全序列化的,并锁定整个数据库,因为它们在更新时间表上发生冲突。
在事务结束时,在更新表中添加一个从NOW()到上述解决方案的时间映射。这似乎需要采取明确的锁定并使用序列来生成非时间“时间戳”,因为只使用单行上的UPDATE会导致SERIALIZABLE模式下的回滚。
不知何故已经PostgreSQL的,在提交时,遍历所有更新的行和设置的updated_at为单调时间戳
不知怎的,有PostgreSQL的本身维护事务的表提交时间,这似乎不这样做此刻
使用内置的xmin列似乎也是不可能的,因为VACUUM可以垃圾它。
如果不修改应用程序中的所有更新,就可以在数据库中执行此操作,这将是非常好的。
这是做什么通常的方式?
与天真的解决方案
如果问题不是很明显,这是用NOW()或CLOCK_TIMESTAMP()问题:
- 在时间1,我们现在运行( )或CLOCK_TIMESTAMP()在交易中给出1,并且我们更新行设置时间1作为更新时间
- 在时间2,客户端获取所有行,并且我们告诉他我们给它所有行,直到时间2
- 在时间3,事务在updated_at字段中提交“时间1”
- 客户机要求自从时间2(他从前一个完全读取请求获得的时间)后更新的行,我们查询updated_at> = 2,并且我们返回任何结果,而不是返回,这只是增加
- 该行损失绝不会为
那仍然不是提交时间,所以它不会工作。即在调用clock_timestamp()后,事务可能会提交一秒,如果客户端在此期间更新,则更新将丢失。 – 2014-11-05 08:30:26
由于相同的原因,这不起作用(除非您在锁定下进行)。 – 2014-11-05 08:44:54
遇到这个确切的问题,寻找答案。 – 2015-01-25 07:22:40