diff options
Diffstat (limited to 'src/mongo/db/index_builds_coordinator.cpp')
-rw-r--r-- | src/mongo/db/index_builds_coordinator.cpp | 46 |
1 files changed, 42 insertions, 4 deletions
diff --git a/src/mongo/db/index_builds_coordinator.cpp b/src/mongo/db/index_builds_coordinator.cpp index da506575b13..7e69b8b0737 100644 --- a/src/mongo/db/index_builds_coordinator.cpp +++ b/src/mongo/db/index_builds_coordinator.cpp @@ -755,9 +755,12 @@ void IndexBuildsCoordinator::applyCommitIndexBuild(OperationContext* opCtx, !opCtx->recoveryUnit()->getCommitTimestamp().isNull()); // There is a possibility that we cannot find an active index build with the given build UUID. - // This can be the case when the index already exists or was dropped on the sync source before - // the collection was cloned during initial sync. The oplog code will ignore the NoSuchKey - // error code. + // This can be the case when: + // - The index already exists during initial sync. + // - The index was dropped on the sync source before the collection was cloned during initial + // sync. + // - A node is restarted with unfinished index builds and --recoverFromOplogAsStandalone. + // The oplog code will ignore the NoSuchKey error code. // // Case 1: Index already exists: // +-----------------------------------------+--------------------------------+ @@ -789,7 +792,42 @@ void IndexBuildsCoordinator::applyCommitIndexBuild(OperationContext* opCtx, // | Apply commitIndexBuild 'x'. | | // | --- Index build not found --- | | // +--------------------------------+--------------------------------+ - auto replState = uassertStatusOK(_getIndexBuild(buildUUID)); + // + // Case 3: Node has unfinished index builds that are not restarted: + // +--------------------------------+-------------------------------------------------+ + // | Before Shutdown | After restart in standalone with | + // | | --recoverFromOplogAsStandalone | + // +--------------------------------+-------------------------------------------------+ + // | startIndexBuild 'x' at TS: 1. | Recovery at TS: 1. | + // | | - Unfinished index build is not restarted. | + // | ***** Checkpoint taken ***** | | + // | | Oplog replay operations starting with TS: 2. | + // | commitIndexBuild 'x' at TS: 2. | Apply commitIndexBuild 'x' oplog entry at TS: 2.| + // | | | + // | | ------------ Index build not found ------------ | + // +--------------------------------+-------------------------------------------------+ + + auto swReplState = _getIndexBuild(buildUUID); + auto replCoord = repl::ReplicationCoordinator::get(opCtx); + + // Index builds are not restarted in standalone mode. If the node is started with + // recoverFromOplogAsStandalone and when replaying the commitIndexBuild oplog entry for a paused + // index, there is no active index build thread to commit. + if (!swReplState.isOK() && replCoord->getSettings().shouldRecoverFromOplogAsStandalone()) { + // Restart the 'paused' index build in the background. + IndexBuilds buildsToRestart; + IndexBuildDetails details{collUUID}; + for (auto spec : oplogEntry.indexSpecs) { + details.indexSpecs.emplace_back(spec.getOwned()); + } + buildsToRestart.insert({buildUUID, details}); + + restartIndexBuildsForRecovery(opCtx, buildsToRestart); + + // Get the builder. + swReplState = _getIndexBuild(buildUUID); + } + auto replState = uassertStatusOK(swReplState); // Retry until we are able to put the index build in the kPrepareCommit state. None of the // conditions for retrying are common or expected to be long-lived, so we believe this to be |