Cassandra删除/更新一行并获取其先前的值

时间:2019-04-27 10:44:03

标签: cassandra cql

如何从Cassandra中删除一行并获取删除前的值?

我可以依次执行一个SELECTDELETE查询,但是如何确定在执行这两个查询之间没有同时更改数据?

我试图批量执行SELECTDELETE查询,但这似乎是不允许的。

cqlsh:foo> BEGIN BATCH
       ...     SELECT * FROM data_by_user WHERE user = 'foo';
       ...     DELETE FROM data_by_user WHERE user = 'foo';
       ... APPLY BATCH;
SyntaxException: line 2:4 mismatched input 'SELECT' expecting K_APPLY (BEGIN BATCH    [SELECT]...)

在我的用例中,我有一个主表来存储项目数据。我已经建立了几个表,可以根据这些信息查找项目。 如果要从主表中删除项目,则还必须将其从其他表中删除。

CREATE TABLE items (id text PRIMARY KEY, owner text, liking_users set<text>, ...);

CREATE TABLE owned_items_by_user (user text, item_id text, PRIMARY KEY ((user), item_id));
CREATE TABLE liked_items_by_user (user text, item_id tect, PRIMARY KEY ((user), item_id));
...

如果我删除一个项目,同时又有人删除了一个表,恐怕表格中可能包含错误的数据。点击相同项目的“赞”按钮。

  • deleteItem方法执行SELECT查询以从主表中获取项目的当前行
  • 同时执行的likeItem方法运行一个UPDATE查询,并将该项目插入到owned_items_by_userliked_items_by_user,...表中。在执行SELECT语句后执行UPDATE查询,然后再执行DELETE查询。
  • deleteItem方法根据刚通过owned_items_by_user语句检索的数据从liked_items_by_userSELECT,...表中删除项目。该数据尚未包含刚刚添加的内容。因此,该项目已删除,但刚刚添加的类似项仍保留在liked_items_by_user表中。

2 个答案:

答案 0 :(得分:2)

您可以事先进行选择,然后对删除执行轻量级事务,以确保数据看起来仍然与选择时完全一样。如果是这样,则在删除之前,您会知道最新状态。如果没有,请继续重试整个过程,直到遇到问题为止。

答案 1 :(得分:0)

不幸的是,您无法在批处理语句中执行$('[name="event"]').on('change', function() { if ($(this).attr('id') == 'walkEvent') { $('#place').text('Meeting point: '); } else { $('#place').text('Location: '); } });查询。如果您阅读文档here,则只能使用插入,更新和删除语句。

您要查找的是执行的原子性,但是批处理语句不会成为前进的方向。如果数据已更改,则最坏的情况是僵尸或可能重新出现的数据。

Cassandra使用成绩周期机制来处理此问题,您可以找到详细信息here。如果出于某种原因这对您的业务逻辑至关重要,那么在这种情况下您可以做的“最好”的事情是提高一致性级别,或者在应用程序级别重构读取模式以不依赖完美的原子性,无论哪种交易正确送给你因此,要么放弃某些性能,要么调低要求。

实际上,<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script> <input type="radio" name="event" id="walkEvent" value="walkEvent"/><label>Walk Event</label> <input type="radio" name="event" id="otherEvent" value="otherEvent"/><label>Other Event</label> <p><label id="place">Meeting Point / Location: </label><input type="text" name="meeting_or_location"/></p>应该足以满足大多数情况下的大多数情况。另外,您可以执行SELECT,并付出性能损失,但这意味着给定QUORUM分区键的所有副本都必须确认ALLfoo。注意,这仍然意味着提交日志中的commitlog必须在删除memtable之前发生,但是您可以将一致性调整到所需的级别。

从SQL的角度来讲,您没有原子性,但是根据吞吐量的不同,您不太可能需要它(触摸木头)。

TLDR:

flush

应该可以解决问题。您现在看到的错误基本上是CQL 3的ANTLR3语法解析器,其设计目的并不是仅仅因为不支持它们而接受批内的SELECT查询,您可以看到 here