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

Pav*_* S. 6 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)
}
Run Code Online (Sandbox Code Playgroud)

这段代码执行后我只是在做select * from demo;cqlsh:

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

cqlsh:demoks> select * from demo;

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

(1 rows)
Run Code Online (Sandbox Code Playgroud)

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

cqlsh:demoks> select * from demo;

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

(1 rows)
Run Code Online (Sandbox Code Playgroud)

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

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

Mar*_*jek 0

基本上无法保证您提供的 insert、upsert 语句将如何最终出现在集群中。大多数时候你会得到你期望的行为,但并非总是如此。这取决于一些因素,你要联系的协调员是什么,那里的时间是什么时候。

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

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

// now execute the batch
session.execute(batch)
Run Code Online (Sandbox Code Playgroud)