C * may lose update after INSERT IF NOT EXISTING

I have the following code:

def main(args: Array[String]): Unit = { val cluster = Cluster.builder() .addContactPoint("localhost") .withPort(9042) .build() val session = cluster.connect() try { session.execute(s"CREATE KEYSPACE demoks WITH REPLICATION = {'class':'SimpleStrategy', 'replication_factor':1}") } catch { case _: AlreadyExistsException => } session.execute(s"USE demoks") session.execute("DROP table IF EXISTS demo") session.execute( """ | CREATE TABLE IF NOT EXISTS demo ( | id text, | data1 map<text, text>, | data2 map<text, text>, | PRIMARY KEY (id) | ) WITH | compaction = {'class': 'LeveledCompactionStrategy'} | AND | compression = { 'sstable_compression' : 'SnappyCompressor' }; """.stripMargin).one() val p1 = session.prepare("UPDATE demo SET data1[?]=?, data2[?] = ? WHERE id=?") val p3 = session.prepare("INSERT INTO demo (id,data1) VALUES (?,?) IF NOT EXISTS") import scala.collection.JavaConverters._ val id2 = "id2-"+System.nanoTime() session.execute(p3.bind(id2, Map("key" -> "value1-q1").asJava)) session.execute(p1.bind("key", "value1-q2", "key", "value2-q2", id2)) System.exit(0) } 

After executing this snippet, I just do select * from demo; in cqlsh :

Usually the result is correct and expected:

 cqlsh:demoks> select * from demo; id | data1 | data2 --------------------+----------------------+---------------------- id2-61510117409472 | {'key': 'value1-q2'} | {'key': 'value2-q2'} (1 rows) 

But sometimes it can be otherwise. It looks like the queries have been reordered and IF NOT EXISTS does not start:

 cqlsh:demoks> select * from demo; id | data1 | data2 --------------------+----------------------+---------------------- id2-61522373234949 | {'key': 'value1-q1'} | {'key': 'value2-q2'} (1 rows) 

Can someone explain this behavior to me?

It Cassandra 3.7 runs in docker on a Windows machine. I cannot reproduce this behavior under Linux and Mac on the same machine and on all other machines. I tried both docker and bare installs. Moreover, I cannot reproduce this even with a simple installation on the same machine.

+6
source share
1 answer

In principle, there is no guarantee how the inserts you entered, statements about the promotion, will be in the cluster. Most of the time you will get the expected behavior, but not always. It depends on some factors, what is the coordinator you click on, what time is there.

You have two options: you set the time yourself on the operators that you create using "use timestamps" or you can use batches to guarantee the order in which your applications are executed:

 // your code Batch batch = QueryBuilder.unloggedBatch() batch.add(binded p3) batch.add(binded p1) // now execute the batch session.execute(batch) 
0
source

All Articles