Car*_*tti 4 java cassandra datastax-java-driver
TL; DR是我无法使用Java删除先前使用upsert创建的行.
基本上我有这样一个表:
CREATE TABLE transactions (
key text PRIMARY KEY,
created_at timestamp
);
Run Code Online (Sandbox Code Playgroud)
然后我执行:
String sql = "update transactions set created_at = toTimestamp(now()) where key = 'test' if created_at = null";
session.execute(sql)
Run Code Online (Sandbox Code Playgroud)
正如预期的那样,行被创建:
cqlsh:thingleme> SELECT * FROM transactions ;
key | created_at
------+---------------------------------
test | 2018-01-30 16:35:16.663000+0000
Run Code Online (Sandbox Code Playgroud)
但是(这是让我发疯的原因)如果我执行:
sql = "delete from transactions where key = 'test'";
ResultSet resultSet = session.execute(sql);
Run Code Online (Sandbox Code Playgroud)
什么都没发生.我的意思是:没有抛出异常而且行仍在那里!
其他一些奇怪的东西:
我的环境:
关于如何解决这个问题的任何想法/建议真的很感激;-)
我认为您遇到的问题可能是通过轻量级事务(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时不同:
轻量级事务将阻止发生其他轻量级事务,但不会阻止正常的读写操作发生.轻量级事务使用与正常操作不同的时间戳机制,并且混合LWT和正常操作可能导致错误.如果使用轻量级事务来写入分区中的行,则只应使用读取和写入操作的轻量级事务.
更复杂的是,默认情况下,java驱动程序使用客户端时间戳,这意味着写时间戳由客户端而不是协调的cassandra节点确定.但是,使用LWT时,会绕过客户端时间戳.在您的情况下,除非您禁用客户端时间戳,否则您的非LWT查询正在使用客户端时间戳,其中您的LWT查询使用cassandra中的paxos逻辑分配的时间戳.在任何情况下,即使驱动程序没有分配客户端时间戳,这仍然可能是一个问题,因为对于LWT和非LWT,时间戳分配逻辑在C*端也是不同的.
要解决此问题,您可以将delete
语句更改为包含IF EXISTS
,即:
delete from transactions where key = 'test' if exists