user3353973
user3353973

Reputation: 83

Neo4j Deadlocks

I'm implementing a Neo4j client for BG benchmark. There are 11 functions, simulating 11 different social networking actions. Each of these functions has its own transaction body. But when I'm running with 100 threads, sometimes it throws deadlock detection exception.

I have users as nodes and friendships as relationships. I have invite friend, reject friend, accept friend and thaw friendship which all have two users as their input. The way they're working is that they're getting all relationships of one user node and find the relationship with the other user node.

Is any one aware of locking mechanism of Neo4j?

Upvotes: 2

Views: 2642

Answers (3)

Liang Tan
Liang Tan

Reputation: 11

Maybe serializing the parallel writing query would be helpful to your solution. In your situation, You have 11 functions, simulating 11 different social networking actions. In your description, I thought that some of the actions(transactions) may be executed in sequential order (e,g, you can only accept friend request after your friend sent an invitation). You may serialize some write transactions. In other words, some queries will be blocked until the previous ones finished. With the help of Causal chaining and bookmarks, you can serialize the operations for each session. For example, if you have three functions, sendInvitationToFriend, reject friend, acceptFriend. reject/accept transactions will be blocked until the sendInvitationToFriend transaction finished.

Some code snippets (neo4j-java-driver 4.1) :


    List<Bookmark> bookmarks = new ArrayList<>();

    // Send Invitation.
    try ( Session session = driver.session( builder().withDefaultAccessMode( AccessMode.WRITE ).build())){
        session.writeTransaction( tx -> this.sendInvitationToFriend( tx, "friendId", "yourId"));
        savedBookmarks.add(session.lastBookmark() );
    }

    // accept the invitation 
    try (Session session = driver.session( builder().withDefaultAccessMode( AccessMode.WRITE ).withBookmarks( savedBookmarks ).build())){
        session.writeTransaction( tx -> this.acceptFriend(tx, "friendId", "yourId"));
    }

    // Create a friendship between the two people created above.
    try (Session session = driver.session(builder().withDefaultAccessMode( AccessMode.WRITE).withBookmarks(savedBookmarks ).build())) {
        session.writeTransaction( tx -> this.rejectFriend( tx, "friendId", "yourId"));
    }

You also mentioned that your simulation is somehow random. My suggestion you could define a retry strategy in your program, re-attempt the query serval times until it goes well and let the main thread to sleep for a while between any two retries. You can find more details information from the link

Wish this post will be helpful to you.

Upvotes: 0

Somnath Muluk
Somnath Muluk

Reputation: 57656

Default locking behaviour:

  1. When adding, changing or removing a property on a node or relationship a write lock will be taken on the specific node or relationship.
  2. When creating or deleting a node a write lock will be taken for the specific node.
  3. When creating or deleting a relationship a write lock will be taken on the specific relationship and both its nodes.

The locks will be added to the transaction and released when the transaction finishes.

  1. Design database in a way that minimum locking will be there.
  2. Avoid using same nodes and relationships are used by many users at same instance. Keep minimum transaction period for those nodes and relationships.

Upvotes: 1

RaduK
RaduK

Reputation: 1463

You can read about the deadlocks in the Neo4j documentation. These can appear when you have concurrent modifications of the same entities (nodes or relationships). Note that when modifying a entity, several locks may be used: for instance for a relationship, the locks on the two nodes connected by the relationship are taken.

Upvotes: 4

Related Questions