diff options
author | Henrik Edin <henrik.edin@mongodb.com> | 2022-08-08 20:38:33 +0000 |
---|---|---|
committer | Evergreen Agent <no-reply@evergreen.mongodb.com> | 2022-09-15 17:27:33 +0000 |
commit | fc0a572b03ef5c589f6e2f89380a83d0142bcba7 (patch) | |
tree | a0f4421d14416160147650dbb043dcd52c47ca58 | |
parent | 3e661ebcc1fc8624472ae7de43a593a556ca8b4f (diff) | |
download | mongo-fc0a572b03ef5c589f6e2f89380a83d0142bcba7.tar.gz |
SERVER-67402 Fix race where linearizable read concern may read during primary catchup
(cherry picked from commit f62d857f440e1340c7338d81c128d0682305f777)
-rw-r--r-- | jstests/replsets/stepup_with_linearizable_read.js | 6 | ||||
-rw-r--r-- | src/mongo/db/storage/snapshot_helper.cpp | 15 |
2 files changed, 13 insertions, 8 deletions
diff --git a/jstests/replsets/stepup_with_linearizable_read.js b/jstests/replsets/stepup_with_linearizable_read.js index abbc2753252..4d3942c8fcf 100644 --- a/jstests/replsets/stepup_with_linearizable_read.js +++ b/jstests/replsets/stepup_with_linearizable_read.js @@ -31,12 +31,12 @@ var sendLinearizableReadOnFailpoint = function() { jsTestLog('Sending in linearizable read in secondary thread'); - // In lock free reads this will timeout as we cannot perform the necessary write after the - // read. Without lock free reads we timeout because we can't acquire the RSTL. + // In lock free reads this will error with NotWritablePrimary. Without lock free reads we + // timeout because we can't acquire the RSTL. assert.commandFailedWithCode( coll.runCommand( {'find': 'foo', readConcern: {level: "linearizable"}, maxTimeMS: 10000}), - ErrorCodes.MaxTimeMSExpired); + [ErrorCodes.NotWritablePrimary, ErrorCodes.MaxTimeMSExpired]); } finally { // Turn off fail point so we can cleanup. assert.commandWorked(db.getMongo().adminCommand( diff --git a/src/mongo/db/storage/snapshot_helper.cpp b/src/mongo/db/storage/snapshot_helper.cpp index a111ff01b55..5a173673158 100644 --- a/src/mongo/db/storage/snapshot_helper.cpp +++ b/src/mongo/db/storage/snapshot_helper.cpp @@ -117,13 +117,18 @@ bool shouldReadAtLastApplied(OperationContext* opCtx, } // Linearizable read concern should never be read at lastApplied, they must always read from - // latest and are only allowed on primaries. + // latest and are only allowed on primaries. We are either a primary not accepting writes or + // secondary at this point, neither which can satisfy the noop write after the read. However, if + // we manage to transition to a writable primary when we do the noop write we may have read data + // during oplog application with kNoTimestamp which should be an error. In both cases it is OK + // to error with NotWritablePrimary here and we do not need to do any further checks after + // acquiring the snapshot because state transitions causes the repl term to increment and we + // can't transition directly from primary to primary catchup without a repl term increase + // happening. if (repl::ReadConcernArgs::get(opCtx).getLevel() == repl::ReadConcernLevel::kLinearizableReadConcern) { - if (reason) { - *reason = "linearizable read concern"; - } - return false; + uasserted(ErrorCodes::NotWritablePrimary, + "cannot satisfy linearizable read concern on non-primary node"); } return true; |