Transactions and locks

Question 1 about Transaction read locks : when doing tx.acquireReadLock on a node, does all relationships linked to this node are also locked, or do we explicitly need to acquire a lock also for them ? Is it possible for a concurrent transaction to delete a relationship linked to a node which has been locked ?

Question 2
Let's say we have the given situation :

Thread 1 (READ-ONLY transaction)
Node node = graphdb.getNodeById(0L);
tx.acquireReadLock(node);
node.getAllProperties();

Thread 2 (WRITE transaction)
Node node = graphdb.getNodeById(0L);
node.delete();

Is it possible to be in the situation where node in Thread 1 still exists (node != null) but write lock has been acquired in Thread 2 before read lock has been acquired in Thread 1 ? If yes, what is the behavior of acquireReadLock ? Is it possible to have a NotFoundException when doing the getAllProperties call even if it is preceded by an acquireReadLock call ?

Question 3
When using a user defined store procedure which uses a org.neo4j.graphdb.Node as field type for the result, is it possible to get a NotFoundException while streaming the results because one of the provided nodes has been deleted by a concurrent transaction ? In this case, does a tx.acquireReadLock should prevent this to happen or should we use a Map<String, Object> (filled by a node.getAllProperties()) instead of Node ?

Question 4 : I have store procedure which is traversing a graph and returns the nodes and relationships traversed. I want to avoid any NotFoundException caused by a concurrent transaction which could delete a node or relationship. Is it enough and advised to call tx.acquireReadLock on each node ?

Thanks a lot.

Our READ-ONLY transactions have 35_000 nodes and 250_000 relationships to give an idea, and can have more. Would be great to know the impact of READ locks on all nodes on performance and memory.
Thanks.

My understanding is that a lock on a node does not lock its relationships. The opposite happens though.

It is definitely possible for thread 2 to delete the node while thread 1 waits for the lock. When thread 2 releases its lock, acquireReadLock will not raise any exception but getAllProperties will throw EntityNotFoundException.

You could just catch the exception in your procedure.

Using explicit locks helps preventing modifications while you're reading from your node, and therefore ensures you read consistent data. If you have a traversal query with several matching steps, it can be useful to make sure the data is consistent between the start and end of the query.
But locks can't prevent a delete between the node matching and the acquisition of the lock.

Ok, thanks for the answers.

Tell me if I am wrong, but I do not see the answer for question 3.

When streaming out results, returning the Node directly would prevent the exception thrown by getAllProperties. But that's not making much difference, as getNode would throw a "Node x not found" if it had been deleted.
That's just the way it is with the "read committed" isolation level. The data you're querying can change mid-query (at least before you explicitly lock it), and you have to deal with the exceptions that may be raised.