INSERT IF NOT EXISTS后,C *可能会丢失更新

时间:2016-09-10 02:27:49

标签: cassandra

我有以下代码:

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)
}

执行此代码段之后,我只是在select * from demo;中执行cqlsh

通常结果是正确的和预期的:

cqlsh:demoks> select * from demo;

 id                 | data1                | data2
--------------------+----------------------+----------------------
 id2-61510117409472 | {'key': 'value1-q2'} | {'key': 'value2-q2'}

(1 rows)

但有时可能会有所不同。看起来查询已重新排序且IF NOT EXISTS未触发:

cqlsh:demoks> select * from demo;

 id                 | data1                | data2
--------------------+----------------------+----------------------
 id2-61522373234949 | {'key': 'value1-q1'} | {'key': 'value2-q2'}

(1 rows)

有人可以解释一下这种行为吗?

这是Cassandra 3.7在Windows机器上的docker中运行。我无法在同一台计算机和所有其他计算机上的Linux或Mac下重现此行为。我尝试了docker和bare安装。而且,即使在同一台机器上进行裸装也无法重现。

1 个答案:

答案 0 :(得分:0)

基本上不保证您提供的insert,upsert语句将如何在群集中结束。大多数情况下,您将获得您期望的行为,但并非总是如此。这取决于一些因素,你所达到的协调员是什么,那里的时间是什么。

您有两个选项,使用“使用时间戳”自行设置您生成的语句的时间,或者您可以使用批处理以保证语句的执行顺序:

// your code
Batch batch = QueryBuilder.unloggedBatch()
batch.add(binded p3)
batch.add(binded p1)

// now execute the batch
session.execute(batch)