2015-11-05 4 views
2

J'ai un problème étrange avec la base de données Cassandra (version 2.2.3) et j'utilise des colonnes statiques pour écrire une preuve de concept pour une application simple avec la fonctionnalité d'envoi d'argent.Échec de la mise à jour de la colonne statique dans cassandra

Ma table est:

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

Première étape ajouter de nouveaux enregistrement

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

Ensuite, je veux 'verrouiller' transaction utilisateur en cours pour faire une action avec son équilibre. J'essaie d'exécuter cette demande:

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

Mais comme résultat dans cqlsh Je vois

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

Je ne comprends pas pourquoi « Faux », parce que les données actuelles pour le profil est:

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

Une idée de ce que je fais mal?

MISE À JOUR

Après lecture Nenad Bozic réponse que je modifie mon exemple pour expliquer pourquoi je dois condition mise à jour. exemple de code complet

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; 

Et si je tente à nouveau de se verrouiller je reçois

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

pourrait être la même question que https://issues.apache.org/jira/browse/CASSANDRA-10532 –

+0

je test dans ' cassandra 3.0.0-rc2' et ça marche ... Mais pas dans d'autres versions ... – greenhost87

Répondre

1

Lorsque vous INSERT vous n'insérez champ lock ce qui signifie que ce champ n'existe pas. La représentation nulle dans CQLSH ou DevCenter n'est que du sucre synthétique pour que les résultats ressemblent à des données tabulaires, mais en réalité, il a des valeurs de clé dynamiques et lock n'est pas présent dans cette carte de valeurs clés. Il est utile de regarder thrift representation de données même si elle n'est plus utilisée pour avoir un sens sur la façon dont elle est stockée sur le disque. Par conséquent, lorsque UPDATE est déclenché, il s'attend à ce que la colonne soit présente pour la mettre à jour. Dans votre cas, la colonne lock n'est même pas présente et ne peut donc pas être mise à jour. Ce thread sur la différence entre INSERT et UPDATE est également bon lire.

Vous avez deux solutions pour faire ce travail:

Insérer null explicitement

Vous pouvez ajouter lock à votre déclaration d'insertion et le mettre à null (ce qui est différent à Cassandra que l'exclure de insert parce que cette façon, il obtiendra valeur nulle et quand vous exclure cette colonne n'existerait pas dans

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

utilisation insérer le deuxième sta Tement

Puisque vous insérez le deuxième déclaration lock pour la première fois, au lieu de mettre à jour la valeur existante et puisqu'elle est la colonne statique pour cette partition, vous pouvez utiliser INSERT IF NOT EXISTS au lieu de UPDATE IF façon LWT de le faire (verrouillage n'existerait donc ce passera première fois et l'échec de tous les autres fois depuis verrouillage aura une valeur):

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

S'il vous plaît voir ma mise à jour – greenhost87

+0

Parce que DE LETE dans Cassandra n'est pas une suppression physique, c'est une suppression logique (la valeur de la colonne est marquée avec une pierre tombale pour la suppression lors du compactage suivant) - http://docs.datastax.com/fr/cql/3.0/cql/cql_using/use_delete.html –

+0

Je suggère d'utiliser des valeurs ici (verrouillé = 1, non verrouillé = 0 ou booléen ou autre) et de changer la valeur en fonction de cela. Dans la première insertion, placez-le sur 0, puis effectuez une mise à jour conditionnelle avec IF lock = 0, etc. Veillez également à ce que Batch ne soit que tout ou rien mais ne puisse pas garantir l'ordre des instructions. –