问题
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:
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)
来源:https://stackoverflow.com/questions/30109292/how-to-manually-manage-neo4j-locks-in-spring-managed-transaction