自上次检查后是否已插入行?

时间:2018-02-15 16:29:23

标签: sql database cqrs

我正在实现一个CQRS模式,其中一个或多个进程将记录插入到数据库中,并且一个或多个进程以不同的速度拉动它们。

我希望消费者流程在数据库中轮询自上次检查后插入的新记录,但我不确定如何(安全地)实现此目的。

您可以假设插入后行不会更改。似乎每行都没有足够的唯一ID,以及表示插入时间的时间戳。

如果我查询时间戳大于我看到的最后一行的记录,那么如果同时插入多个记录(具有相同的时间戳),我会遇到问题。

如果我查询id大于我看到的最后一行的记录,那么我遇到了并发事务可能以非递增顺序提交ID的问题(例如,postgreSQL会话提前分配和缓存序列ID以提高性能)

理想情况下,我正在寻找与DBMS无关的解决方案,并且能够尽可能接近实时地使用数据。有什么想法吗?

澄清:每个消费者应该多次使用每一行。这意味着,仅仅因为一个消费者处理一行不应该阻止其他消费者这样做。每个消费者都会使用相同的数据做一些不同的事情。

2 个答案:

答案 0 :(得分:0)

由于您有大量数据进入并且上一个时间戳可能有多个记录,因此您需要一种方法来跟踪读取的数据。以下是一些不同的方法,包括它们的优点和缺点:

  1. 您可以等待数据进入时间戳。您可以通过不读取MAX(timestamp)来执行此操作,这样您就可以获得表中的所有数据,除了数据可能仍会进入的最后一个数据。
  2. Pro:简单设计

    骗局:不是实时处理

    1. 您可以存储每次读取最后一个时间戳的ID。获取数据时,您可以使用(timestamp = lasttimestamp and id not in (set of ids)) or timestamp > lasttimestamp)
    2. 之类的查询

      亲:几乎是实时

      Con:需要额外存储空间

答案 1 :(得分:0)

如果您不使用分片或类似内容:

您可以使用乐观锁定

为此,您可以创建order列,在记录表(日志)上使用唯一索引。在每次插入之前,生产者向Log查询最大order,它会递增它并插入带有此order的下一条记录。

如果发生并发异常(即Duplicate entry '12345' for key order),则重试整个过程(查询,增量,插入)。

如果您使用分片或类似内容:

然后,您将需要一个额外的服务/表,每次要求它生成一个新的,唯一的,始终增加的order整数。

这样做的缺点是必须管理另一个部分,一个必须高度可用的单点故障。

P.S。

  • “分片或类似”意味着您不能在整个表上拥有唯一索引,因为您使用分片或写入多个表。
  • 您不能依赖时间戳或任何与物理时间相关的内容,因为系统时间可以通过自动服务(NTP)或人工操作员进行调整。