2015-11-05 67 views
2

我有Cassandra(版本2.2.3)数据库的奇怪问题,并使用发送资金功能编写简单应用程序的概念证明时使用静态列。无法更新cassandra中的静态列

我的表是:

CREATE TABLE transactions (
profile text, 
timestamp timestamp, 
amount text, 
balance text, 
lock int static, 
PRIMARY KEY (profile, timestamp)) WITH CLUSTERING ORDER BY (timestamp ASC); 

第一步我添加新的记录

INSERT INTO transactions (profile, timestamp, amount) VALUES ('test_profile', '2015-11-05 15:20:01+0000', '10USD'); 

然后我想“锁定”当前用户的交易做一些动作与他的平衡。我尝试执行此请求:

UPDATE transactions SET lock = 1 WHERE profile = 'test_profile' IF lock = null; 

但作为结果cqlsh我看到

 [applied] 
----------- 
    False 

我不明白为什么“假”,因为轮廓当前数据是:

profile  | timestamp    | lock | amount | balance 
--------------+--------------------------+------+--------+--------- 
test_profile | 2015-11-05 15:20:01+0000 | null | 10USD | null 

任何想法我做错了什么?

UPDATE

读内纳德Bozic医师的回答后,我改变我的例子来阐明为什么我需要更新条件。完整的代码示例

CREATE TABLE transactions (
    profile text, 
    timestamp timestamp, 
    amount text, 
    balance text, 
    lock int static, 
    balances map<text,text> static, 
    PRIMARY KEY (profile, timestamp) 
) WITH CLUSTERING ORDER BY (timestamp ASC); 
INSERT INTO transactions (profile, timestamp, amount) VALUES ('test_profile', '2015-11-05 15:20:01+0000', '1USD'); 
INSERT INTO transactions (profile, lock) VALUES ('test_profile', 1) IF NOT EXISTS; 
BEGIN BATCH 
     UPDATE transactions SET balances={'USD':'1USD'} WHERE profile='test_profile'; 
     UPDATE transactions SET balance='1USD' WHERE profile='test_profile' AND timestamp='2015-11-05 15:20:01+0000'; 
     DELETE lock FROM transactions WHERE profile='test_profile'; 
APPLY BATCH; 

如果我尝试再次获得锁我得到

INSERT INTO transactions (profile, lock) VALUES ('test_profile', 1) IF NOT EXISTS; 

[applied] | profile  | timestamp | balances  | lock | amount | balance 
-----------+--------------+-----------+-----------------+------+--------+--------- 
    False | test_profile |  null | {'USD': '1USD'} | null | null | null 
+0

可能是相同的问题https://issues.apache.org/jira/browse/CASSANDRA-10532 –

+0

我在'考cassandra 3.0.0-rc2'和它的工作原理...但不能在其他版本中工作... – greenhost87

回答

1

当你INSERT你不插入lock场,这意味着这个领域不存在。 CQLSH或DevCenter中的空值表示仅仅是合成糖,使结果看起来像表格数据,但实际上它具有动态键值,并且lock不存在于键值的映射中。查看数据的thrift representation是有用的,即使它不再用于了解数据如何存储到磁盘。

因此,当UPDATE被激活时,期望列出现以更新它。在你的情况下,lock列甚至不存在,所以它不能更新它。这个threadINSERTUPDATE之间的区别也是很好的阅读。

你有两个解决方案,以使这项工作:

插入空明确

您可以添加lock到您的插入语句,并将其设置为null(在Cassandra是不同的比从插入排除它因为这样一来就会得到空值,当你排除此列不会在

INSERT INTO transactions (profile, timestamp, amount, lock) 
VALUES ('test_profile', '2015-11-05 15:20:01+0000', '10USD', null); 

存在使用上插入第二STA tement

既然你是在第二条语句lock将首次,而不是更新现有的价值,因为它是该分区的静态列,您可以用INSERT IF NOT EXISTS,而不是做这件事的UPDATE IF LWT方式(锁就不会存在,所以这将通过第一次失败的所有其他时间,因为锁将有值):

INSERT INTO transactions (profile, lock) 
VALUES ('test_profile', 1) IF NOT EXISTS; 
+0

请查看我的更新 – greenhost87

+0

由于DE Cassandra中的LETE不是物理删除,而是逻辑删除(在下一次压缩时列值被标记为逻辑删除) - http://docs.datastax.com/en/cql/3.0/cql/cql_using/use_delete.html –

+0

我建议在这里使用值(锁定= 1,不锁定= 0或布尔值或其他)并根据此值切换值。在第一次插入时,将它设置为0,然后使用IF锁定= 0等方式进行条件更新。同时要注意,批量只是全部或全部操作,但它不能保证语句的顺序。 –