[SERVER-39672] ReadConcern level in multi-statement transactions defaults to "snapshot" Created: 19/Feb/19  Updated: 29/Oct/23  Resolved: 28/Mar/19

Status: Closed
Project: Core Server
Component/s: Replication
Affects Version/s: None
Fix Version/s: 4.1.10, 4.0.10

Type: Bug Priority: Major - P3
Reporter: A. Jesse Jiryu Davis Assignee: Lingzhi Deng
Resolution: Fixed Votes: 0
Labels: None
Remaining Estimate: Not Specified
Time Spent: Not Specified
Original Estimate: Not Specified

Issue Links:
Backports
Depends
Documented
is documented by DOCS-12871 Investigate changes in SERVER-39672: ... Closed
Problem/Incident
Related
is related to SERVER-39274 Mongos should not upconvert transacti... Closed
Backwards Compatibility: Minor Change
Operating System: ALL
Backport Requested:
v4.0
Sprint: Repl 2019-03-25, Repl 2019-04-08
Participants:
Linked BF Score: 63

 Description   

If a user starts a transaction with no readConcern level (the default), the transaction reads from the all-committed snapshot instead of at the last applied timestamp. The expected behavior is if there is no readConcern level it behaves the same as an explicit readConcern level "local" and reads from the last applied timestamp.

Transactions with an explicit readConcern level "local" behave correctly, the bug affects the default common case, with no explicit level.

Details: In _extractReadConcern in service_entry_point common, if we're starting a multi-statement transaction, we save the user's readConcern level as ReadConcernArgs::_originalLevel, and replace ReadConcernArgs::_level with kSnapshot. Later, we determine whether to read from a snapshot by calling ReadConcernArgs::getOriginalLevel(). judah.schvimer says the intention of this is to make readConcern::getLevel() return kSnapshot in all multi-statement transactions. He says "We upconvert all readconcerns to snapshot for ease of coding, but we use the original read concern level when calling _setSpeculativeTransactionOpTime". (I, Jesse, don't know how this eases coding yet.)

However, getOriginalLevel() doesn't fulfill this intention. If the client provides no readConcern, then ReadConcernArgs::_originalLevel is boost::none. Then getOriginalLevel() does:

    return _originalLevel.value_or(getLevel());

... which is the upconverted level, "snapshot"!



 Comments   
Comment by A. Jesse Jiryu Davis [ 16/Jul/19 ]

Thank you!

Comment by wei [ 16/Jul/19 ]

jesse I have filed SERVER-42250 for the situation. Thanks for checking this.

Comment by A. Jesse Jiryu Davis [ 13/Jul/19 ]

Thanks for your comment, Wei Li. Could you please open a new Jira ticket with some more details about the jobs you're running and when you see write conflicts, how your replica set is configured, what version you're running, perhaps some sample code that reproduces the issue? Then we can give you a precise answer.

Comment by wei [ 10/Jul/19 ]

Before we get the update to the formal docs, can we have some explanation why this can cause write conflict issues.

  • we have jobs running in readConcern: snapshot seeing many write conflicts, but readConcern: local simply passes
  • our job does not have any real write conflicts so that seeing many write conflicts is strange to us
  • this is running only one primary in replset mode without any secondaries: unsure whether it changed behavior

As this write conflict is not the normal write skew from snapshot consistency system, what is causing this?

Thanks,

Comment by A. Jesse Jiryu Davis [ 10/Jul/19 ]

Agreed, bartle, we'll update the docs there.

Comment by David Bartley [ 10/Jul/19 ]

It might be worth calling this change out on https://docs.mongodb.com/manual/reference/read-concern/#read-concern-levels? We ran into this ourselves and were pretty confused by what was going on.

Comment by Luke Chen [ 11/Apr/19 ]

Fixing up fixversion as this ticket was not included as part of 4.0.9 release.

Comment by Githook User [ 05/Apr/19 ]

Author:

{'name': 'Lingzhi Deng', 'username': 'ldennis', 'email': 'lingzhi.deng@mongodb.com'}

Message: SERVER-39672: default to local if no read concern specified for a multi-statment transaction

(cherry picked from commit 74fd169e8867b4633d4c1677055dda74e3460238)
Branch: v4.0
https://github.com/mongodb/mongo/commit/1ab343a48799b42074e0056e9f486ed0c444956d

Comment by Lingzhi Deng [ 28/Mar/19 ]

I think this is a minor behavior change because now startTransaction() defaults to "local" read concern if no read concern is provided. Due to the bug described in this ticket, startTransaction() used to run with read concern "snapshot" by default.

Comment by Githook User [ 28/Mar/19 ]

Author:

{'email': 'max.hirschhorn@mongodb.com', 'name': 'Max Hirschhorn', 'username': 'visemet'}

Message: SERVER-39672 Fix lint.
Branch: master
https://github.com/mongodb/mongo/commit/cf14abb8e454edc042d5f4ad1768f19321135a79

Comment by Githook User [ 27/Mar/19 ]

Author:

{'email': 'lingzhi.deng@mongodb.com', 'name': 'Lingzhi Deng', 'username': 'ldennis'}

Message: SERVER-39672: default to local if no read concern specified for a multi-statment transaction
Branch: master
https://github.com/mongodb/mongo/commit/74fd169e8867b4633d4c1677055dda74e3460238

Comment by A. Jesse Jiryu Davis [ 20/Feb/19 ]

We clearly had made the same mistake in mongos (SERVER-39274), investigate the relationship b/w that bug and this one, and in what version these bugs were introduced.

Generated at Thu Feb 08 04:52:46 UTC 2024 using Jira 9.7.1#970001-sha1:2222b88b221c4928ef0de3161136cc90c8356a66.