From 6a031f67c7040b925a36e8092c4f5d36510d68f2 Mon Sep 17 00:00:00 2001 From: Benety Goh Date: Fri, 11 Sep 2020 13:41:01 -0400 Subject: SERVER-50519 index build is resumable only if commit quorum is the default (i.e. all-voters) and node is a voter --- jstests/noPassthrough/indexbg_restart_secondary.js | 14 +++---------- src/mongo/db/SConscript | 1 + src/mongo/db/index_builds_coordinator.cpp | 23 ++++++++++++++++++++-- .../db/storage/two_phase_index_build_knobs.idl | 1 - 4 files changed, 25 insertions(+), 14 deletions(-) diff --git a/jstests/noPassthrough/indexbg_restart_secondary.js b/jstests/noPassthrough/indexbg_restart_secondary.js index 52d49479e6b..a740c1ded7e 100644 --- a/jstests/noPassthrough/indexbg_restart_secondary.js +++ b/jstests/noPassthrough/indexbg_restart_secondary.js @@ -73,7 +73,6 @@ replTest.start(second, { setParameter: { "failpoint.hangAfterSettingUpIndexBuildUnlocked": tojson({mode: "alwaysOn"}), - "failpoint.hangAfterSettingUpResumableIndexBuild": tojson({mode: "alwaysOn"}) } }, /*restart=*/true, @@ -93,14 +92,9 @@ try { // Verify that we do not wait for the index build to complete on startup. assert.eq(size, secondDB.getCollection(collectionName).find({}).itcount()); - // Verify that only the _id index is ready. - const supportsCommittedReads = - assert.commandWorked(secondDB.serverStatus()).storageEngine.supportsCommittedReads; - if (ResumableIndexBuildTest.resumableIndexBuildsEnabled(second) && supportsCommittedReads) { - checkLog.containsJson(second, 4841704); - } else { - checkLog.containsJson(second, 4585201); - } + // The hangAfterSettingUpIndexBuildUnlocked fail point logs this message when it is active. + checkLog.containsJson(second, 4585201); + IndexBuildTest.assertIndexes(secondDB.getCollection(collectionName), 4, ["_id_"], @@ -109,8 +103,6 @@ try { } finally { assert.commandWorked(second.adminCommand( {configureFailPoint: 'hangAfterSettingUpIndexBuildUnlocked', mode: 'off'})); - assert.commandWorked(second.adminCommand( - {configureFailPoint: 'hangAfterSettingUpResumableIndexBuild', mode: 'off'})); // Let index build complete on primary, which replicates a commitIndexBuild to the secondary. IndexBuildTest.resumeIndexBuilds(primaryDB); diff --git a/src/mongo/db/SConscript b/src/mongo/db/SConscript index a0c8de84714..14706fa55ce 100644 --- a/src/mongo/db/SConscript +++ b/src/mongo/db/SConscript @@ -934,6 +934,7 @@ env.Library( '$BUILD_DIR/mongo/db/dbhelpers', '$BUILD_DIR/mongo/db/repl/repl_coordinator_interface', + '$BUILD_DIR/mongo/db/repl/replica_set_messages', '$BUILD_DIR/mongo/db/repl/timestamp_block', '$BUILD_DIR/mongo/db/s/sharding_api_d', '$BUILD_DIR/mongo/db/storage/encryption_hooks', diff --git a/src/mongo/db/index_builds_coordinator.cpp b/src/mongo/db/index_builds_coordinator.cpp index d27dd0848db..3ff70329b4d 100644 --- a/src/mongo/db/index_builds_coordinator.cpp +++ b/src/mongo/db/index_builds_coordinator.cpp @@ -420,13 +420,19 @@ bool isIndexBuildResumable(OperationContext* opCtx, return false; } + // Only index builds with the default "all-voters" commit quorum running on voting nodes should + // be resumable. A node that cannot contribute to the commit quorum should not be waiting for + // the majority commit point when trying to commit the index build. // IndexBuildsOptions::commitQuorum will be set if we are primary. Otherwise, we have to check // the config.system.indexBuilds collection. if (indexBuildOptions.commitQuorum) { - if (indexBuildOptions.commitQuorum->numNodes == CommitQuorumOptions::kDisabled) { + if (CommitQuorumOptions::kVotingMembers != indexBuildOptions.commitQuorum->mode) { return false; } } else { + // The commit quorum may be updated using the setIndexBuildCommitQuorum command, so we will + // rely on the deadline to unblock ourselves from the majority wait if the commit quorum is + // no longer "all-voters". auto swCommitQuorum = indexbuildentryhelpers::getCommitQuorum(opCtx, replState.buildUUID); if (!swCommitQuorum.isOK()) { LOGV2(5044600, @@ -437,11 +443,24 @@ bool isIndexBuildResumable(OperationContext* opCtx, return false; } auto commitQuorum = swCommitQuorum.getValue(); - if (commitQuorum.numNodes == CommitQuorumOptions::kDisabled) { + if (CommitQuorumOptions::kVotingMembers != commitQuorum.mode) { return false; } } + // Ensure that this node is a voting member in the replica set config. + auto rsConfig = replCoord->getConfig(); + auto hap = replCoord->getMyHostAndPort(); + if (auto memberConfig = rsConfig.findMemberByHostAndPort(hap)) { + if (!memberConfig->isVoter()) { + return false; + } + } else { + // We cannot determine our member config, so skip the majority wait and leave this index + // build as non-resumable. + return false; + } + return true; } diff --git a/src/mongo/db/storage/two_phase_index_build_knobs.idl b/src/mongo/db/storage/two_phase_index_build_knobs.idl index 0d52b29128a..f14e7c9bd60 100644 --- a/src/mongo/db/storage/two_phase_index_build_knobs.idl +++ b/src/mongo/db/storage/two_phase_index_build_knobs.idl @@ -62,7 +62,6 @@ server_parameters: build will proceed as a non-resumable index build. Set to 0 to skip the wait. This will also disable resumable index builds. Set to a negative value to wait indefinitely for the majority commit point. - TODO(SERVER-50519): Set default to -1. set_at: startup cpp_vartype: long long cpp_varname: gResumableIndexBuildMajorityOpTimeTimeoutMillis -- cgit v1.2.1