Write blocking behavior in neo4j cypher over trans-national REST api

I am using CYPHER as shown below (with Neo4j 2.2.3, above transactional kef REST endpoint) to atomically read and increment the counter property on a node:

MATCH node WHERE id(node)={nodeId}
SET node.counter=COALESCE(node.counter,0) + 1
RETURN node.counter

      

I have multiple threads creating REST records like this and now I've seen a case where two threads got the same counter value.

This behavior is similar to what is described as a possible regression from 2.1 to 2.2: Neo4j 2.2 Cypher Lock Regression?

However, it has previously been suggested that this is not possible in CYPHER (see comments here: https://stackoverflow.com/a/1499298/ ... ) ... even before, it seems like it was possible (see: https://stackoverflow.com/a/2996999/) 2250118 / ... )

Is there a CYPHER request similar to the one above that will reliably generate unique (monotonically increasing) counter values โ€‹โ€‹when there are multiple concurrent REST requests?

+3


source to share


3 answers


In Neo4j, you need to acquire a write lock before reading and updating a value. We do this as two statements in one transaction (one REST call). We are using MERGE / ON CREATE / ON MATCH, but I don't think this is necessary or even will work in your case. I believe this should work for you.

expression 1:

MATCH node WHERE id(node)={nodeId}
SET node.__lock=true
RETURN node.__lock

      



expression 2:

MATCH node WHERE id(node)={nodeId}
SET node.counter=COALESCE(node.counter,0) + 1
SET node.__lock=false
RETURN node.counter

      

+1


source


Short solution:

MATCH node WHERE id(node)={nodeId}
SET 
  node.__lock=true, 
  node.counter=COALESCE(node.counter,0) + 1,
  node.__lock=false
RETURN node.counter

      



This is an improved solution by Sean Timm. This notation is more efficient (faster) than two transactions

+2


source


Adding to @SeanTimm's answer, you can explicitly block nodes via Cypher, if you are using the popular (and open source) APOC plugin for Neo4j, APOC has a choice of explicit blocking routines that can be called via Cypher such ascall apoc.lock.nodes([nodes])

If this option is available to you, it is probably preferable to some other hacky solutions.

More on neo4j-contrib.github.io/neo4j-apoc-procedures/#_locking

0


source







All Articles