2

Imagine a query like this:

match (i:QuestionOrder) 
set i.count=i.count+1 
merge (q:Question {text: '+text here+', index: i.count}) 
return q

Neo4j guarantees write locks if sets occur within the same transaction which is implied by the same query in node-neo4j. However, I'm getting the following output:

[
  {
    "columns":["q"],
    "data":[{"text":"Have Kids...","index":1,"_id":542}]
  },
  {
    "columns":["q"],
    "data":[{"text":"You are...","index":1,"_id":545}]
  }
]

From my understanding, a lock should prevent index from being the same. Am I missing something here? How can I resolve this?

Brian Underwood
  • 10,746
  • 1
  • 22
  • 34
Ben Reed
  • 824
  • 1
  • 8
  • 26

1 Answers1

0

Probably it helps for concurrent work to change this query to add an additional test. If you have two concurrent transactions, the lock is grabbed at the set-operation. So both have already read i.count and are waiting with the same value.

So either you grab that lock earlier:

match (i:QuestionOrder) 
set i.lock = NOT i.lock
set i.count=i.count+1 
merge (q:Question {text: '+text here+', index: i.count}) 
return q

or you add an additional check that avoids the merge to happen (then you have to retry)

match (i:QuestionOrder) 
WITH i, i.count + 1 as new_count
set i.count = new_count
WITH i, new_count
WHERE i.count = new_count
merge (q:Question {text: '+text here+', index: i.count}) 
return q

Or send two different statements in the same tx of which the first does the locking.

Michael Hunger
  • 41,339
  • 3
  • 57
  • 80