无法删除以前使用 Java 在 Cassandra 中使用更新插入创建的行

Can't delete a row previously created with an upsert in Cassandra using Java

TL;DR 是我无法删除以前使用 Java.

的更新插入创建的行

基本上我有这样一个 table:

CREATE TABLE transactions (
key text PRIMARY KEY,
created_at timestamp
);

然后我执行:

String sql = "update transactions set created_at = toTimestamp(now()) where key = 'test' if created_at = null"; 
session.execute(sql)

如预期的那样创建了行:

cqlsh:thingleme> SELECT * FROM  transactions ;

 key  | created_at
------+---------------------------------
 test | 2018-01-30 16:35:16.663000+0000

但是(这让我发疯)如果我执行:

sql = "delete from transactions where key = 'test'"; 
ResultSet resultSet = session.execute(sql);

没有任何反应。我的意思是:没有抛出异常并且该行仍然存在!

其他一些奇怪的东西:

我的环境:

任何关于如何解决这个问题的 idea/suggestion 非常感谢;-)

我认为您遇到的问题可能是轻量级事务 (LWT) (update transactions set created_at = toTimestamp(now()) where key = 'test' if created_at = null) 和非 LWT (delete from transactions where key = 'test') 混合使用造成的。

Cassandra 使用时间戳来确定哪些变更(删除、更新)是最近应用的。使用 LWT 时,时间戳分配与不使用 LWT 时不同:

Lightweight transactions will block other lightweight transactions from occurring, but will not stop normal read and write operations from occurring. Lightweight transactions use a timestamping mechanism different than for normal operations and mixing LWTs and normal operations can result in errors. If lightweight transactions are used to write to a row within a partition, only lightweight transactions for both read and write operations should be used.

来源:How do I accomplish lightweight transactions with linearizable consistency?

更复杂的是,默认情况下,java 驱动程序使用客户端时间戳,这意味着写入时间戳由客户端而不是协调的 cassandra 节点确定。但是,当您使用 LWT 时,客户端时间戳将被绕过。在您的情况下,除非您禁用客户端时间戳,否则您的非 LWT 查询将使用客户端时间戳,而您的 LWT 查询将使用由 cassandra 中的 paxos 逻辑分配的时间戳。在任何情况下,即使驱动程序没有分配客户端时间戳,这仍然可能是一个问题,因为时间戳分配逻辑在 C* 端对于 LWT 和非 LWT 也是不同的。

要解决此问题,您可以更改 delete 语句以包含 IF EXISTS,即:

delete from transactions where key = 'test' if exists

Similar issue from the java driver mailing list