2016-09-10 11 views
6

Mam następujący kod:C * może stracić aktualizacji po INSERT IF NOT EXISTS

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

Po wykonaniu tego fragmentu Robię select * from demo; w cqlsh:

Zwykle wynik jest poprawny i oczekiwano:

cqlsh:demoks> select * from demo; 

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

(1 rows) 

Czasami może być inaczej. Wygląda na to, że zapytania została zmieniona i IF NOT EXISTS nie wywołał:

cqlsh:demoks> select * from demo; 

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

(1 rows) 

Czy ktoś może mi wyjaśnić to zachowanie?

To Cassandra 3.7 działa w oknie dokowanym na komputerze z systemem Windows. Nie mogę odtworzyć tego zachowania w systemie Linux ani Mac na tym samym komputerze i na wszystkich innych komputerach. Próbowałem zarówno dokowania, jak i nagich instalacji. Co więcej, nie mogę tego odtworzyć nawet po instalacji na tej samej maszynie.

+0

powinieneś prawdopodobnie opublikuj swój kod klienta, aby zrozumieć, co się dzieje. – xmas79

+0

Dobra, zamieściłem fragment kodu. –

+0

Ponownie, przepraszam, powinieneś również zamieścić uszkodzone dane. Dokładnie, powinieneś zamieścić swój kod klienta i to, co otrzymasz. Trudno powiedzieć bez patrzenia na to. – xmas79

Odpowiedz

0

Zasadniczo nie ma gwarancji, że wstawiane instrukcje wstawiania danych upsert zostaną zakończone w klastrze. Zazwyczaj osiągasz oczekiwane zachowanie, ale nie zawsze. To zależy od kilku czynników, od tego, jaki koordynator kręcisz, jaki jest czas.

Masz dwie opcje ustawienie czasu dla siebie oświadczenia można produkować przy użyciu „przy użyciu znacznika czasu” lub użyć partii, tak aby zagwarantować kolejność wykonywania swoich stwierdzeń:

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

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