3
votes

First of all I will explain why I would like to manually set write locks. I use Neo4j database in my web service application based on Spring Data Neo4j. Transactions are managed by Spring, I just use @Transactional annotation. However, I have problem with specific use case which leads to database inconsistency. I have a method that is transactional and its aim is to make such nodes/relation in database:

(p:Person)-[:USES]->(s:SIM_Card{phoneNumber:"xxx"})

Its algorithm is as follows:

-check if there is a SIM_Card with specific phone number (unique) already in the database (cypher query through @Query),

-if yes get this node and if no create it,

-check if there is any Person attached to this SIM_Card with USES relation (cypher query),

-if there is no such Person create it and attach to SIM_Card.

Unfortunately when there are many requests it happens that I have in database SIM_Cards that are attached to more than one Person. I assume that method is executed by two concurrent threads. Both read database and search for SIM_Card with the same phone number, and both get the information that there is no such SIM_Card in database yet, so they create them, and then they attach two separate Person to them. PhoneNuber is unique for SIM_Card, so eventually there is only one SIM_Card, but two Person remains and it is not expected situation. To fix this I would like to create SIM_Card in separate Transaction and then create Person and attach to this SIM_Card in another transaction. Before the Person is created I will check if there is no Person already attached. However, just before that check I would like to set a write lock manually on SIM_Card and I assume that then other Transaction would not be able to check in meantime if there is/or not any Person connected to this SIM_Card. It would have to wait for the lock to be released and then it will see that this SIM_Card has Person attached and would not create another one.

To achieve that I have to get somehow ability to set Neo4j locks inside @Transactional annotated method and I do not know how to do that. I would really appreciate your help.

1
did you find a solution for this case ? Currently I ran into the same issue and don't know how to acquire the write lock in order to properly update my counters.alexanoid
Please consider my question: stackoverflow.com/questions/50665958/… @Transactional has isolation attribute which would possibly help. But unfortunately, Neo4jTransactionManager throws exception in doBegin() method if this setting deviates from default: github.com/spring-projects/spring-data-neo4j/blob/master/…PAX
Anyhow, a reasonable support has never been implemented since years: github.com/neo4j/neo4j/issues/1103PAX

1 Answers

0
votes

I think you have to give up @Transactional in this case, wire GraphDatabaseService instance into your repository (or service), and start the transaction and acquire the write lock manually (http://neo4j.com/docs/stable/javadocs/org/neo4j/graphdb/Transaction.html#acquireWriteLock(org.neo4j.graphdb.PropertyContainer)