mirror of
https://github.com/mongodb/mongo.git
synced 2024-11-30 17:10:48 +01:00
SERVER-41769 Pin _currentCommittedSnapshot to be <= the allCommitted timestamp when EMRC=false
This commit is contained in:
parent
2dfbaadb85
commit
795b99ef36
@ -17,7 +17,8 @@
|
||||
|
||||
// Insert a document that gets deleted as part of the transaction.
|
||||
const kDeletedDocumentId = 0;
|
||||
coll.insert({_id: kDeletedDocumentId, a: "I was here before the transaction"});
|
||||
coll.insert({_id: kDeletedDocumentId, a: "I was here before the transaction"},
|
||||
{writeConcern: {w: "majority"}});
|
||||
|
||||
let cst = new ChangeStreamTest(db);
|
||||
let changeStream = cst.startWatchingChanges({
|
||||
|
@ -47,7 +47,7 @@
|
||||
|
||||
// Insert a document unmodified by the transaction.
|
||||
const otherDoc = {_id: 2, y: 2};
|
||||
assert.commandWorked(testColl.insert(otherDoc));
|
||||
assert.commandWorked(testColl.insert(otherDoc, {writeConcern: {w: "majority"}}));
|
||||
|
||||
// Create an index on 'y' to avoid conflicts on the field.
|
||||
assert.commandWorked(testColl.createIndex({y: 1}));
|
||||
|
@ -0,0 +1,61 @@
|
||||
/**
|
||||
* This tests that writes with majority write concern will wait for at least the all committed
|
||||
* timestamp to reach the timestamp of the write. This guarantees that once a write is majority
|
||||
* committed, reading at the all committed timestamp will read that write.
|
||||
*/
|
||||
(function() {
|
||||
"use strict";
|
||||
|
||||
load("jstests/libs/check_log.js");
|
||||
|
||||
function assertWriteConcernTimeout(result) {
|
||||
assert.writeErrorWithCode(result, ErrorCodes.WriteConcernFailed);
|
||||
assert(result.hasWriteConcernError(), tojson(result));
|
||||
assert(result.getWriteConcernError().errInfo.wtimeout, tojson(result));
|
||||
}
|
||||
|
||||
const rst = new ReplSetTest({name: "writes_wait_for_all_committed", nodes: 1});
|
||||
rst.startSet();
|
||||
rst.initiate();
|
||||
|
||||
const primary = rst.getPrimary();
|
||||
const dbName = "test";
|
||||
const collName = "majority_writes_wait_for_all_committed";
|
||||
const testDB = primary.getDB(dbName);
|
||||
const testColl = testDB[collName];
|
||||
|
||||
TestData.dbName = dbName;
|
||||
TestData.collName = collName;
|
||||
|
||||
testDB.runCommand({drop: collName, writeConcern: {w: "majority"}});
|
||||
assert.commandWorked(testDB.createCollection(collName, {writeConcern: {w: "majority"}}));
|
||||
|
||||
assert.commandWorked(testDB.adminCommand({
|
||||
configureFailPoint: "hangAfterCollectionInserts",
|
||||
mode: "alwaysOn",
|
||||
data: {collectionNS: testColl.getFullName(), first_id: "b"}
|
||||
}));
|
||||
|
||||
jsTestLog(
|
||||
"Insert a document to hang before the insert completes to hold back the all committed timestamp.");
|
||||
const joinHungWrite = startParallelShell(() => {
|
||||
assert.commandWorked(
|
||||
db.getSiblingDB(TestData.dbName)[TestData.collName].insert({_id: "b"}));
|
||||
}, primary.port);
|
||||
jsTestLog("Checking that the log contains fail point enabled.");
|
||||
checkLog.contains(
|
||||
testDB.getMongo(),
|
||||
"hangAfterCollectionInserts fail point enabled for " + testColl.getFullName());
|
||||
|
||||
try {
|
||||
jsTest.log("Do a write with majority write concern that should time out.");
|
||||
assertWriteConcernTimeout(
|
||||
testColl.insert({_id: 0}, {writeConcern: {w: "majority", wtimeout: 2 * 1000}}));
|
||||
} finally {
|
||||
assert.commandWorked(
|
||||
primary.adminCommand({configureFailPoint: 'hangAfterCollectionInserts', mode: 'off'}));
|
||||
}
|
||||
|
||||
joinHungWrite();
|
||||
rst.stopSet();
|
||||
})();
|
@ -3597,11 +3597,17 @@ void ReplicationCoordinatorImpl::_setStableTimestampForStorage(WithLock lk) {
|
||||
stableOpTime->opTime.getTimestamp());
|
||||
}
|
||||
} else {
|
||||
// When majority read concern is disabled, the stable optime may be ahead of the
|
||||
// commit point, so we set the committed snapshot to the commit point.
|
||||
const auto lastCommittedOpTime = _topCoord->getLastCommittedOpTimeAndWallTime();
|
||||
if (!lastCommittedOpTime.opTime.isNull()) {
|
||||
_updateCommittedSnapshot_inlock(lastCommittedOpTime);
|
||||
// When majority read concern is disabled, we set the stable timestamp to
|
||||
// be less than or equal to the all committed timestamp. This makes sure that
|
||||
// the committed snapshot is not past the all committed timestamp to guarantee
|
||||
// we can always read our own majority committed writes. This problem is
|
||||
// specific to the case where we have a single node replica set and the
|
||||
// lastCommittedOpTime is set to be the lastApplied which can be ahead of the
|
||||
// allCommitted.
|
||||
auto newCommittedSnapshot = std::min(lastCommittedOpTime, *stableOpTime);
|
||||
_updateCommittedSnapshot_inlock(newCommittedSnapshot);
|
||||
}
|
||||
// Set the stable timestamp regardless of whether the majority commit point moved
|
||||
// forward.
|
||||
|
Loading…
Reference in New Issue
Block a user