<p dir="auto">For example, I have this data on my Neo4J (I'm using v2.2.5):</p>
<div class="snippet-clipboard-content notranslate position-relative overflow-auto" data-snippet-clipboard-copy-content="merge (a1:Actor {id: &quot;1&quot;})
merge (m1:Movie {id: &quot;M1&quot;})
merge (m2:Movie {id: &quot;M2&quot;})
merge (m3:Movie {id: &quot;M3&quot;})
merge (a1)-[:ACTED_IN]-&gt;(m1)
merge (a1)-[:ACTED_IN]-&gt;(m2)
merge (a1)-[:ACTED_IN]-&gt;(m3);"><pre class="notranslate"><code class="notranslate">merge (a1:Actor {id: "1"})
merge (m1:Movie {id: "M1"})
merge (m2:Movie {id: "M2"})
merge (m3:Movie {id: "M3"})
merge (a1)-[:ACTED_IN]-&gt;(m1)
merge (a1)-[:ACTED_IN]-&gt;(m2)
merge (a1)-[:ACTED_IN]-&gt;(m3);
</code></pre></div>
<p dir="auto">Then I have two concurrent process that run these query:</p>
<p dir="auto">Process-1:</p>
<div class="snippet-clipboard-content notranslate position-relative overflow-auto" data-snippet-clipboard-copy-content="MATCH (n:Actor {uuid: '1'}) 
CREATE (n)-[:ACTED_IN]-&gt;(m:Movie) 
RETURN m;"><pre class="notranslate"><code class="notranslate">MATCH (n:Actor {uuid: '1'}) 
CREATE (n)-[:ACTED_IN]-&gt;(m:Movie) 
RETURN m;
</code></pre></div>
<p dir="auto">Process-2:</p>
<div class="snippet-clipboard-content notranslate position-relative overflow-auto" data-snippet-clipboard-copy-content="MATCH (n:Actor {uuid: '1'}) 
OPTIONAL MATCH (n)-[r]-() 
DELETE n, r;"><pre class="notranslate"><code class="notranslate">MATCH (n:Actor {uuid: '1'}) 
OPTIONAL MATCH (n)-[r]-() 
DELETE n, r;
</code></pre></div>
<p dir="auto">Process-1 will create a new relationship and a new Movie node for the Actor and process-2 will delete the Actor and its relationships.</p>
<p dir="auto">When the both process are run in same time, the delete (process-2) sometimes failed with this error:</p>
<div class="snippet-clipboard-content notranslate position-relative overflow-auto" data-snippet-clipboard-copy-content="org.neo4j.kernel.api.exceptions.TransactionFailureException:  Node record Node[11,used=false,rel=4,prop=-1,labels=Inline(0x0:[]),light] still has relationships"><pre class="notranslate"><code class="notranslate">org.neo4j.kernel.api.exceptions.TransactionFailureException:  Node record Node[11,used=false,rel=4,prop=-1,labels=Inline(0x0:[]),light] still has relationships
</code></pre></div>
<p dir="auto">or</p>
<div class="snippet-clipboard-content notranslate position-relative overflow-auto" data-snippet-clipboard-copy-content="Node[1208] is deleted and cannot be used to create a relationship"><pre class="notranslate"><code class="notranslate">Node[1208] is deleted and cannot be used to create a relationship
</code></pre></div>
<p dir="auto">The delete failed because the delete query try to delete 3 ACTED_IN relationships from the Actor node, while when the DELETE command was just being executed, the process-1 query had successfully created a new ACTED_IN relationship (see analysis part below).</p>
<p dir="auto">I managed to reproduce the error with this bash script (you need to have <code class="notranslate">curl</code> program):</p>
<div class="snippet-clipboard-content notranslate position-relative overflow-auto" data-snippet-clipboard-copy-content="#!/bin/bash

curl -XPOST http://localhost:7474/db/data/transaction/commit -H &quot;Content-Type: application/json&quot; -d '{&quot;statements&quot; : [ {&quot;statement&quot; : &quot;MATCH (n:Actor {id: \&quot;1\&quot;}) OPTIONAL MATCH (n)-[r]-() DELETE n, r&quot;} ]}' &amp;
curl -XPOST http://localhost:7474/db/data/transaction/commit -H &quot;Content-Type: application/json&quot; -d '{&quot;statements&quot; : [ {&quot;statement&quot; : &quot;MATCH (n:Actor {id: \&quot;1\&quot;}) CREATE (n)-[:ACTED_IN]-&gt;(m:Movie) RETURN m&quot;} ]}' &amp;

wait"><pre class="notranslate"><code class="notranslate">#!/bin/bash

curl -XPOST http://localhost:7474/db/data/transaction/commit -H "Content-Type: application/json" -d '{"statements" : [ {"statement" : "MATCH (n:Actor {id: \"1\"}) OPTIONAL MATCH (n)-[r]-() DELETE n, r"} ]}' &amp;
curl -XPOST http://localhost:7474/db/data/transaction/commit -H "Content-Type: application/json" -d '{"statements" : [ {"statement" : "MATCH (n:Actor {id: \"1\"}) CREATE (n)-[:ACTED_IN]-&gt;(m:Movie) RETURN m"} ]}' &amp;

wait
</code></pre></div>
<p dir="auto">Note: You might need to re-run the script again and clear up the database and reinsert the nodes again if the error doesn't show up as the process are executed concurrently, the issue doesn't always show up.</p>
<p dir="auto">I wonder if when a cypher is executed, is there node or relationship locking being applied?</p>
<p dir="auto">If looking from the problem above, I have a feeling there are no locking at all. From my analysis:</p>
<div class="snippet-clipboard-content notranslate position-relative overflow-auto" data-snippet-clipboard-copy-content="MATCH (n:Actor {uuid: '1'}) // n = Actor node
OPTIONAL MATCH (n)-[r]-()   // r = 3 ACTED_IN relationships

// However, before reaching the DELETE command below, 
// the Process-1's query has been executed inbetween, 
// so currently the Actor node actually has 4 ACTED_IN relationships

DELETE n, r;  // Since the Actor has 4 relationships 
              // but the variable r still refer to 3 relationships only, 
              // so this made the delete failed"><pre class="notranslate"><code class="notranslate">MATCH (n:Actor {uuid: '1'}) // n = Actor node
OPTIONAL MATCH (n)-[r]-()   // r = 3 ACTED_IN relationships

// However, before reaching the DELETE command below, 
// the Process-1's query has been executed inbetween, 
// so currently the Actor node actually has 4 ACTED_IN relationships

DELETE n, r;  // Since the Actor has 4 relationships 
              // but the variable r still refer to 3 relationships only, 
              // so this made the delete failed
</code></pre></div>
<p dir="auto">I would expect when a cypher query is executed or run, neo4j will lock the processed node &amp; relationship from being modified by other cypher process, so the other query process should wait until it finished.</p>
<p dir="auto">Is there an explanation and solution for this?</p>
<p dir="auto">Is there a way to lock the node or relationship from being modified by another process?</p>
<p dir="auto"><em>NOTE: This description has been updated, the original description is at the bottom</em></p>
<p dir="auto">While Neo4j primitives are <code class="notranslate">read committed</code>, Cypher composes these primitives together in ways that can lead to errors - notably cypher may read an entity that is subsequently deleted, and will then fail to perform some operation on it.</p>
<p dir="auto">While this could be construed as a cypher issue, it is really an issue of isolation levels - we need to implement <code class="notranslate">repeatable read</code> isolation in the kernel to allow cypher to expose a single cypher statement as a read committed operation.</p>
<h3 dir="auto">If you suspect an isolation issue</h3>
<p dir="auto">If you believe you are hitting a problem related to transaction isolation levels, please post a comment on this ticket with:</p>
<ul dir="auto">
<li>Any setup required</li>
<li>All cypher statements involved</li>
<li>What you expected the result to be</li>
<li>What the result actually is</li>
<li>Your Neo4j version, Java version and operating system</li>
</ul>
<h2 dir="auto">Workarounds</h2>
<h3 dir="auto">Lock the read set</h3>
<p dir="auto">Many (but not all) of the cases where this is an issue have a format like:</p>
<div class="snippet-clipboard-content notranslate position-relative overflow-auto" data-snippet-clipboard-copy-content="&lt;match some stuff&gt;
&lt;perform some mutation&gt;"><pre class="notranslate"><code class="notranslate">&lt;match some stuff&gt;
&lt;perform some mutation&gt;
</code></pre></div>
<p dir="auto">For this category of statements, we suffer the same problem as SQL solves with <code class="notranslate">SELECT ... FOR UPDATE</code>. Cypher does not yet support a construct like that, but it can be emulated using the following pattern:</p>
<div class="snippet-clipboard-content notranslate position-relative overflow-auto" data-snippet-clipboard-copy-content="&lt;match some stuff&gt;
&lt;set a property, for instance __lock__&gt;
WITH &lt;stuff&gt;
&lt;perform some mutation&gt;"><pre class="notranslate"><code class="notranslate">&lt;match some stuff&gt;
&lt;set a property, for instance __lock__&gt;
WITH &lt;stuff&gt;
&lt;perform some mutation&gt;
</code></pre></div>
<p dir="auto">For example:</p>
<div class="snippet-clipboard-content notranslate position-relative overflow-auto" data-snippet-clipboard-copy-content="MATCH (n:Person)
SET n.__lock__ = 1
WITH n
SET n.description = &quot;Some description&quot;"><pre class="notranslate"><code class="notranslate">MATCH (n:Person)
SET n.__lock__ = 1
WITH n
SET n.description = "Some description"
</code></pre></div>
<h3 dir="auto">Retry transaction</h3>
<p dir="auto">Particularly for small read operations and small writes, given the transactional nature of Neo4j, you can rollback and retry any transaction where a statement fails due to this issue. A common pattern for this is to model your query as a unit of work that can be retried.</p>
<h2 dir="auto">Original message</h2>
<p dir="auto"><a class="user-mention notranslate" data-hovercard-type="user" data-hovercard-url="/users/peterneubauer/hovercard" data-octo-click="hovercard-link-click" data-octo-dimensions="link_type:self" href="https://github.com/peterneubauer">@peterneubauer</a>: 'See <a href="https://groups.google.com/group/neo4j/browse_thread/thread/9355edd2059d70e2/a51d06c894107327?lnk=gst&amp;q=Concurrent+reading+and+deleting+on+relationships+leads+to+NotFoundException.+How+to+ignore%3F#a51d06c894107327" rel="nofollow">https://groups.google.com/group/neo4j/browse_thread/thread/9355edd2059d70e2/a51d06c894107327?lnk=gst&amp;q=Concurrent+reading+and+deleting+on+relationships+leads+to+NotFoundException.+How+to+ignore%3F#a51d06c894107327</a> for background.</p>
<p dir="auto">Example code is at <a href="http://code.google.com/p/graph-query-benchmarks/source/browse/trunk/graph-query-benchmarks/src/test/nz/ac/massey/cs/graphbenchmarks/spikes/neo4j/NeoIssues.java" rel="nofollow">http://code.google.com/p/graph-query-benchmarks/source/browse/trunk/graph-query-benchmarks/src/test/nz/ac/massey/cs/graphbenchmarks/spikes/neo4j/NeoIssues.java</a>'</p>