-
Type: Improvement
-
Resolution: Fixed
-
Priority: Major - P3
-
Affects Version/s: None
-
Component/s: None
-
Minor Change
-
v4.2, v4.0
-
Repl 2020-02-10, Repl 2020-02-24
Currently, most txnNumber errors refer only to transactions, even if the error pertains to a retryable write. This can create a poor user experience for someone who is only using retryable writes.
We should audit these types of errors on the server and determine whether the command was a part of a retryable write or a transaction. Depending on the answer, we can return one of the following errors:
"Cannot start transaction X on session <UUID> because a newer transaction or retryable write with txnNumber Y has already started on this session."
"Retryable write with txnNumber X is prohibited on session <UUID> because a newer transaction or retryable write with txnNumber Y has already started on this session."
ORIGINAL POST:
Code that reproduces the issue:
private static async Task TestSingleSession(MongoClient client) { var col = client.GetDatabase("_test").GetCollection<BsonDocument>("concurrent"); using (var session = await client.StartSessionAsync()) { var ops = Enumerable.Range(0, 100) .Select(async e => { await col.ReplaceOneAsync(session, Builders<BsonDocument>.Filter.Eq("_id", e), new BsonDocument { { "_id", e }, { "data", $"someData_{e}" }, }, new UpdateOptions { IsUpsert = true }); }) .ToArray(); await Task.WhenAll(ops); } }
When running above code I'm getting the exception:
MongoCommandException: Command update failed: Cannot start transaction 1 on session c4fd4081-e0f0-40d6-84fc-cdfeccc74e3b - hf9LJrhq2lfp667gnURrBVE7MCUS1NJZYDmWlqfKWl0= because a newer transaction 3 has already started..
This is misleading as there's no explicit transaction in progress.
I know now that we should use either
- ReplaceOneAsync overload without session
- Create new session per call to ReplaceOneAsync with session
background: I've encountered that issue in production code where one method is being used with and without transaction - our solution was to simply create a intermediate overloaded method that creates a session for you and passes it into method that accepts the session.
- is related to
-
SERVER-35411 Add abortCause argument to abortActiveTransaction and save it on the session
- Backlog
-
DRIVERS-699 Raise an actionable error message when retryWrites fails due to using an unsupported storage engine
- Closed