无法更新 cassandra 中的静态列

Failed to update static column in cassandra

我在使用 Cassandra(版本 2.2.3)数据库和使用静态列时遇到奇怪的问题,当我为具有汇款功能的简单应用程序编写一些概念证明时。

我的table是:

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');

然后我想'lock'当前用户交易用他的余额做一些动作。我尝试执行这个请求:

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

但是我看到了 cqlsh 的结果

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

我不明白为什么 'False',因为配置文件的当前数据是:

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

知道我哪里做错了吗?

更新

阅读 Nenad 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

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

所以当 UPDATE 被触发时,它期望列存在以更新它。在您的情况下 lock 列甚至不存在,因此无法更新它。关于 INSERTUPDATE 之间差异的 thread 也很好读。

你有两个解决方案来完成这项工作:

显式插入 null

您可以将 lock 添加到您的插入语句并将其设置为空(这在 Cassandra 中不同于将其从插入中排除,因为这样它将获得空值,并且当您排除它时,该列不会存在于

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

在第二条语句上使用插入

由于您是第一次在第二条语句 lock 上插入而不是更新现有值,并且由于它是该分区的静态列,您可以使用 INSERT IF NOT EXISTS 而不是 UPDATE IF LWT这样做的方式(锁不存在,所以这将在第一次通过并且所有其他时间都失败,因为锁将具有价值):

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