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

问题描述 投票:0回答:2

如何从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表中。
cassandra cql
2个回答
2
投票

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


0
投票

不幸的是,您无法在批处理语句中执行SELECT查询。如果您阅读文档here,则只能使用insert,update和delete语句。

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

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

在实践中,QUORUM应该足以满足大多数情况下的大多数情况。或者,您可以执行ALL,并且您支付性能损失,但这意味着给定foo分区键的所有副本将必须在commitlogmemtable中确认写入。注意,这仍然意味着在删除是flush之前需要发生来自commitlog的complete,但是您可以将一致性调整到所需的级别。

你没有SQL意义上的原子性,但根据吞吐量,你不太可能需要它(触摸木材)。

TLDR:

USE CONSISTENCY ALL;
DELETE FROM data_by_user WHERE user = 'foo';

这应该够了吧。你现在看到的错误基本上是CQL 3的ANTLR3语法解析器,它不是为了接受批量内部的SELECT查询而仅仅因为它们不受支持,你可以看到here

最新问题
© www.soinside.com 2019 - 2025. All rights reserved.