0
0
mirror of https://github.com/mongodb/mongo.git synced 2024-12-01 09:32:32 +01:00

SERVER-45064 single phased index builds do not generate startIndexBuild or commitIndexBuild oplog entries

This commit is contained in:
Benety Goh 2020-01-08 12:56:21 +00:00 committed by evergreen
parent 7e675af0b6
commit accf5bb6e6
2 changed files with 22 additions and 56 deletions

View File

@ -56,14 +56,19 @@ assert.neq(0, exitCode, 'expected shell to exit abnormally due to index build be
IndexBuildTest.assertIndexes(coll, 1, ['_id_']);
const cmdNs = testDB.getCollection('$cmd').getFullName();
let ops = rst.dumpOplog(primary, {op: 'c', ns: cmdNs, 'o.startIndexBuild': coll.getName()});
assert.eq(1, ops.length, 'incorrect number of startIndexBuild oplog entries: ' + tojson(ops));
if (IndexBuildTest.supportsTwoPhaseIndexBuild(primary)) {
let ops = rst.dumpOplog(primary, {op: 'c', ns: cmdNs, 'o.startIndexBuild': coll.getName()});
assert.eq(1, ops.length, 'incorrect number of startIndexBuild oplog entries: ' + tojson(ops));
ops = rst.dumpOplog(primary, {op: 'c', ns: cmdNs, 'o.abortIndexBuild': coll.getName()});
assert.eq(1, ops.length, 'incorrect number of abortIndexBuild oplog entries: ' + tojson(ops));
ops = rst.dumpOplog(primary, {op: 'c', ns: cmdNs, 'o.commitIndexBuild': coll.getName()});
assert.eq(0, ops.length, 'incorrect number of commitIndexBuild oplog entries: ' + tojson(ops));
} else {
// The noop oplog entry is the only evidence of the failed single phase index build.
let ops = rst.dumpOplog(
primary, {op: 'n', ns: '', 'o.msg': 'Creating indexes. Coll: ' + coll.getFullName()});
assert.eq(1, ops.length, 'incorrect number of noop oplog entries: ' + tojson(ops));
}
ops = rst.dumpOplog(primary, {op: 'c', ns: cmdNs, 'o.commitIndexBuild': coll.getName()});
assert.eq(0, ops.length, 'incorrect number of commitIndexBuild oplog entries: ' + tojson(ops));
rst.stopSet();
})();

View File

@ -124,17 +124,10 @@ void onCommitIndexBuild(OperationContext* opCtx,
const NamespaceString& nss,
const ReplIndexBuildState& replState,
bool replSetAndNotPrimaryAtStart) {
if (!serverGlobalParams.featureCompatibility.isVersionInitialized()) {
return;
}
if (serverGlobalParams.featureCompatibility.getVersion() !=
ServerGlobalParams::FeatureCompatibility::Version::kFullyUpgradedTo44) {
return;
}
const auto& buildUUID = replState.buildUUID;
invariant(IndexBuildProtocol::kTwoPhase == replState.protocol,
str::stream() << "onCommitIndexBuild: " << buildUUID);
invariant(opCtx->lockState()->isWriteLocked(),
str::stream() << "onCommitIndexBuild: " << buildUUID);
@ -143,23 +136,6 @@ void onCommitIndexBuild(OperationContext* opCtx,
const auto& indexSpecs = replState.indexSpecs;
auto fromMigrate = false;
if (IndexBuildProtocol::kTwoPhase != replState.protocol) {
// Do not expect replication state to change during committing index build when two phase
// index builds are not in effect because the index build would be aborted (most likely due
// to a stepdown) before we reach here.
if (replSetAndNotPrimaryAtStart) {
// Get a timestamp to complete the index build in the absence of a commitIndexBuild
// oplog entry.
repl::UnreplicatedWritesBlock uwb(opCtx);
if (!IndexTimestampHelper::setGhostCommitTimestampForCatalogWrite(opCtx, nss)) {
log() << "Did not timestamp index commit write.";
}
return;
}
opObserver->onCommitIndexBuild(opCtx, nss, collUUID, buildUUID, indexSpecs, fromMigrate);
return;
}
// Since two phase index builds are allowed to survive replication state transitions, we should
// check if the node is currently a primary before attempting to write to the oplog.
auto replCoord = repl::ReplicationCoordinator::get(opCtx);
@ -823,26 +799,16 @@ void IndexBuildsCoordinator::createIndexesOnEmptyCollection(OperationContext* op
invariant(
UncommittedCollections::get(opCtx).hasExclusiveAccessToCollection(opCtx, collection->ns()));
// Emit startIndexBuild and commitIndexBuild oplog entries if supported by the current FCV.
auto opObserver = opCtx->getServiceContext()->getOpObserver();
auto buildUUID = serverGlobalParams.featureCompatibility.isVersionInitialized() &&
serverGlobalParams.featureCompatibility.getVersion() ==
ServerGlobalParams::FeatureCompatibility::Version::kFullyUpgradedTo44
? boost::make_optional(UUID::gen())
: boost::none;
if (buildUUID) {
opObserver->onStartIndexBuild(opCtx, nss, collectionUUID, *buildUUID, specs, fromMigrate);
}
// If two phase index builds are enabled, the index build will be coordinated using
// startIndexBuild and commitIndexBuild oplog entries.
auto indexCatalog = collection->getIndexCatalog();
if (supportsTwoPhaseIndexBuild()) {
invariant(buildUUID, str::stream() << collectionUUID << ": " << nss);
// All indexes will be added to the mdb catalog using the commitIndexBuild timestamp.
opObserver->onCommitIndexBuild(opCtx, nss, collectionUUID, *buildUUID, specs, fromMigrate);
auto buildUUID = UUID::gen();
opObserver->onStartIndexBuild(opCtx, nss, collectionUUID, buildUUID, specs, fromMigrate);
opObserver->onCommitIndexBuild(opCtx, nss, collectionUUID, buildUUID, specs, fromMigrate);
for (const auto& spec : specs) {
uassertStatusOK(indexCatalog->createIndexOnEmptyCollection(opCtx, spec));
}
@ -853,10 +819,6 @@ void IndexBuildsCoordinator::createIndexesOnEmptyCollection(OperationContext* op
opObserver->onCreateIndex(opCtx, nss, collectionUUID, spec, fromMigrate);
uassertStatusOK(indexCatalog->createIndexOnEmptyCollection(opCtx, spec));
}
if (buildUUID) {
opObserver->onCommitIndexBuild(
opCtx, nss, collectionUUID, *buildUUID, specs, fromMigrate);
}
}
}
@ -1109,10 +1071,7 @@ Status IndexBuildsCoordinator::_setUpIndexBuild(OperationContext* opCtx,
}
MultiIndexBlock::OnInitFn onInitFn;
if (serverGlobalParams.featureCompatibility.isVersionInitialized() &&
serverGlobalParams.featureCompatibility.getVersion() ==
ServerGlobalParams::FeatureCompatibility::Version::kFullyUpgradedTo44) {
if (IndexBuildProtocol::kTwoPhase == replIndexBuildState->protocol) {
// Two-phase index builds write a different oplog entry than the default behavior which
// writes a no-op just to generate an optime.
onInitFn = [&](std::vector<BSONObj>& specs) {
@ -1715,17 +1674,19 @@ void IndexBuildsCoordinator::_insertKeysFromSideTablesAndCommit(
uassertStatusOK(
_indexBuildsManager.checkIndexConstraintViolations(opCtx, replState->buildUUID));
// Generate both createIndexes and commitIndexBuild oplog entries.
// Secondaries currently interpret commitIndexBuild commands as noops.
// If two phase index builds is enabled, index build will be coordinated using
// startIndexBuild and commitIndexBuild oplog entries.
auto onCommitFn = [&] {
if (IndexBuildProtocol::kTwoPhase != replState->protocol) {
return;
}
onCommitIndexBuild(
opCtx, collection->ns(), *replState, indexBuildOptions.replSetAndNotPrimaryAtStart);
};
auto onCreateEachFn = [&](const BSONObj& spec) {
// If two phase index builds is enabled, index build will be coordinated using
// startIndexBuild and commitIndexBuild oplog entries.
if (supportsTwoPhaseIndexBuild()) {
if (IndexBuildProtocol::kTwoPhase == replState->protocol) {
return;
}