Following the document, I operation transaction like this:
Transaction txn = dgraphClient.newTransaction();
try {
// Do something here
// ...
} finally {
txn.discard();
}
It works well if I run single thread.
But if I run this in multi-threads, it throws below exception:
Exception in thread "pool-2-thread-5" io.dgraph.TxnConflictException: Transaction has been aborted. Please retry.
at io.dgraph.DgraphClient$Transaction.checkAndThrowException(DgraphClient.java:315)
at io.dgraph.DgraphClient$Transaction.commit(DgraphClient.java:256)
I don’t see the data you are trying to mutate. If your code is mutating the same nodes in Dgraph concurrently, then it is possible that a TxnConflictException is thrown. This is to prevent the data in Dgraph from getting inconsistent. You have a couple of options:
Check for TxnConflictException and retry the transaction with some sort of backoff. Eventually it will succeed once other conflicting transactions have been committed.
Make sure concurrent threads are never operating on the same nodes, so that there is no chance of a conflict.
Ok, in that case I am not really sure under what conditions the server can issue a transaction conflict exception. It could be a problem in the Java client, but it’s unlikely. I will ask the folks working on the server to take a look here, and respond before I investigate the client further.
Meanwhile, you could still try retrying the transaction with backoff, and see how it goes.
@deepakjois I try retrying the transaction, It can be successful after many retry times. Some times, I get this exception:
[pool-2-thread-1] ERROR com.haizhi.graph.lab.dgraph.datamaker.DgraphDataMaker - Node create error:
io.dgraph.TxnConflictException: Conflicts with pending transaction. Please abort.
at io.dgraph.DgraphClient$Transaction.checkAndThrowException(DgraphClient.java:315)
at io.dgraph.DgraphClient$Transaction.mutate(DgraphClient.java:228)
at com.haizhi.graph.lab.dgraph.datamaker.DgraphDataMaker.saveVertices(DgraphDataMaker.java:127)
Something similar happened to me.
With many mutations to the same indexed predicate, the predicate is being indexed and thus conflicts occur.
This can safely be ignored with the Mutation.setIgnoreIndexConflict(true)if you’re doing updates (as opposed to upserts)
I believe the rationale is, you made two concurrent mutations to the same predicate, mutation #1 created a new node and the index is being reindexed. Mutation #2 might perform a query beforehand (within its transaction) to ascertain if there’s a particular node. Since the index is being refreshed, the query might/will not yield the result created in #1.