Closed 6ther closed 9 months ago
Hi @6ther, I don't know how this didn't get picked up by my issues notifications, so apologies for the delayed response. here is an article about this exception for a bit of explanation: https://neo4j.com/developer/kb/explanation-of-error-deadlockdetectedexception-forseticlient-0-cant-acquire-exclusivelock/
This is a transient exception you can retry the transaction. Which method on the driver are you using to invoke the query/transaction?
Hi @6ther, I don't know how this didn't get picked up by my issues notifications, so apologies for the delayed response. here is an article about this exception for a bit of explanation: https://neo4j.com/developer/kb/explanation-of-error-deadlockdetectedexception-forseticlient-0-cant-acquire-exclusivelock/
This is a transient exception you can retry the transaction. Which method on the driver are you using to invoke the query/transaction?
like this: var session = _driver.Session(); using var tran = session.BeginTransaction(); tran.Run(query, parameters) tran.Commit();
Hi @6ther, I don't know how this didn't get picked up by my issues notifications, so apologies for the delayed response. here is an article about this exception for a bit of explanation: https://neo4j.com/developer/kb/explanation-of-error-deadlockdetectedexception-forseticlient-0-cant-acquire-exclusivelock/
This is a transient exception you can retry the transaction. Which method on the driver are you using to invoke the query/transaction?
like this: var session = _driver.Session(); using var tran = session.BeginTransaction(); tran.Run(query, parameters) tran.Commit();
first of all, thanks for your reply and an article about this exception.
@6ther You have a few options here:
Use your own retry mechanism with your explicit transaction by catching TransientException, rollback that transaction and try it again.
var retries = 0;
while (true)
{
var tx = await session.BeginTransactionAsync();
try
{
var cursor = await tx.RunAsync("UNWIND RANGE(1, 100) AS x RETURN x");
var results = await cursor.ToListAsync();
await tx.CommitAsync();
}
catch (TransientException)
{
await tx.RollbackAsync();
retries++;
if (retries > 5) throw;
await Task.Delay(500);
}
}
Use the "transaction functions" ExecuteReadAsync/ExecuteWriteAsync.
var results = await session.ExecuteReadAsync(async tx =>
{
var cursor = await tx.RunAsync("UNWIND RANGE(1, 100) AS x RETURN x");
return cursor.ToListAsync();
}
);
the driver [ExecutableQuery](), it works nicely for single query transactions.
var results = await driver.ExecutableQuery("UNWIND RANGE(1, 100) AS x RETURN x")
.WithConfig(new QueryConfig(RoutingControl.Readers, "neo4j"))
.ExecuteAsync();
@6ther You have a few options here:
- Use your own retry mechanism with your explicit transaction by catching TransientException, rollback that transaction and try it again.
var retries = 0; while (true) { var tx = await session.BeginTransactionAsync(); try { var cursor = await tx.RunAsync("UNWIND RANGE(1, 100) AS x RETURN x"); var results = await cursor.ToListAsync(); await tx.CommitAsync(); } catch (TransientException) { await tx.RollbackAsync(); retries++; if (retries > 5) throw; await Task.Delay(500); } }
- Use the "transaction functions" ExecuteReadAsync/ExecuteWriteAsync.
var results = await session.ExecuteReadAsync(async tx => { var cursor = await tx.RunAsync("UNWIND RANGE(1, 100) AS x RETURN x"); return cursor.ToListAsync(); } );
- the driver ExecutableQuery, it works nicely for single query transactions.
var results = await driver.ExecutableQuery("UNWIND RANGE(1, 100) AS x RETURN x") .WithConfig(new QueryConfig(RoutingControl.Readers, "neo4j")) .ExecuteAsync();
Thanks for your advice, and i still have some questions.
When I set configuration like this:
IDriver _driver = GraphDatabase.Driver(uri, AuthTokens.Basic(user, password), (b) => { b.WithDefaultReadBufferSize(250000) .WithDefaultWriteBufferSize(125000) .WithMaxReadBufferSize(1250000) .WithMaxWriteBufferSize(1250000) **.WithMaxTransactionRetryTime(TimeSpan.FromSeconds(30));** }); _driver.Session().BeginTransaction(t => **t.WithTimeout(TimeSpan.FromSeconds(30))**);
Can the transaction retry?
Can the tranaction retry?
_driver.Session().BeginTransaction(t => **t.WithTimeout(TimeSpan.FromSeconds(30)));
the driver can not do any retry mechanisms automatically for you when you use this method.
With regards to:
.WithMaxTransactionRetryTime(TimeSpan.FromSeconds(30))
This config only has an effect on ISession.ExecuteRead
, ISession.ExecuteWrite
, and IDriver.ExecutableQuery
.
If you would like to make use of the ISession
interface and have retries on your transactions you must use ExecuteRead
and ExecuteWrite
.
Here is an example:
using var driver = GraphDatabase.Driver(
uri,
AuthTokens.Basic(user, password),
cfg => cfg.WithDefaultReadBufferSize(250000)
.WithDefaultWriteBufferSize(125000)
.WithMaxReadBufferSize(1250000)
.WithMaxWriteBufferSize(1250000)
.WithMaxTransactionRetryTime(TimeSpan.FromSeconds(30)));
using var session = driver.Session(x => x.WithDatabase("neo4j"));
var results = session.ExecuteRead(
tx => tx.Run(query, parameters).ToList(),
cfg => cfg.WithTimeout(TimeSpan.FromSeconds(30)));
Can the tranaction retry?
_driver.Session().BeginTransaction(t => **t.WithTimeout(TimeSpan.FromSeconds(30)));
the driver can not do any retry mechanisms automatically for you when you use this method.
With regards to:
.WithMaxTransactionRetryTime(TimeSpan.FromSeconds(30))
This config only has an effect on
ISession.ExecuteRead
,ISession.ExecuteWrite
, andIDriver.ExecutableQuery
.If you would like to make use of the
ISession
interface and have retries on your transactions you must useExecuteRead
andExecuteWrite
. Here is an example:using var driver = GraphDatabase.Driver( uri, AuthTokens.Basic(user, password), cfg => cfg.WithDefaultReadBufferSize(250000) .WithDefaultWriteBufferSize(125000) .WithMaxReadBufferSize(1250000) .WithMaxWriteBufferSize(1250000) .WithMaxTransactionRetryTime(TimeSpan.FromSeconds(30))); using var session = driver.Session(x => x.WithDatabase("neo4j")); var results = session.ExecuteRead( tx => tx.Run(query, parameters).ToList(), cfg => cfg.WithTimeout(TimeSpan.FromSeconds(30)));
I understand. Thanks for your answer and thanks a lot.
@6ther you are welcome, can I close this issue?
@6ther you are welcome, can I close this issue?
Yes.
Neo4j.Driver.TransientException: ForsetiClient[transactionId=169062, clientId=2734] can't acquire ExclusiveLock{owner=ForsetiClient[transactionId=169064, clientId=2731]} on NODE(359109), because holders of that lock are waiting for ForsetiClient[transactionId=169062, clientId=2734].