summaryrefslogtreecommitdiff
path: root/src/mongo/db
diff options
context:
space:
mode:
authorBenety Goh <benety@mongodb.com>2019-11-08 16:25:40 +0000
committerevergreen <evergreen@mongodb.com>2019-11-08 16:25:40 +0000
commit02cef2152d32e04f6f8149dd7923f977b417ffb2 (patch)
tree3a000b043cd51f21b6fd29e018713cbb315dbdcc /src/mongo/db
parent4b92498a94f42790d2f6a3f26a965acb1de4702f (diff)
downloadmongo-02cef2152d32e04f6f8149dd7923f977b417ffb2.tar.gz
SERVER-44393 split IndexBuildsCoordinator::_buildIndex() into hybrid index build phases
Diffstat (limited to 'src/mongo/db')
-rw-r--r--src/mongo/db/index_builds_coordinator.cpp48
-rw-r--r--src/mongo/db/index_builds_coordinator.h49
2 files changed, 97 insertions, 0 deletions
diff --git a/src/mongo/db/index_builds_coordinator.cpp b/src/mongo/db/index_builds_coordinator.cpp
index aea56abc00b..a1bed562111 100644
--- a/src/mongo/db/index_builds_coordinator.cpp
+++ b/src/mongo/db/index_builds_coordinator.cpp
@@ -1248,6 +1248,22 @@ void IndexBuildsCoordinator::_buildIndex(
std::shared_ptr<ReplIndexBuildState> replState,
const IndexBuildOptions& indexBuildOptions,
boost::optional<Lock::CollectionLock>* exclusiveCollectionLock) {
+ _scanCollectionAndInsertKeysIntoSorter(opCtx, dbAndUUID, replState, exclusiveCollectionLock);
+ auto nss = _insertKeysFromSideTablesWithoutBlockingWrites(opCtx, dbAndUUID, replState);
+ auto commitIndexBuildTimestamp = _waitForCommitOrAbort(opCtx, nss, replState);
+ _insertKeysFromSideTablesAndCommit(opCtx,
+ dbAndUUID,
+ replState,
+ indexBuildOptions,
+ exclusiveCollectionLock,
+ commitIndexBuildTimestamp);
+}
+
+void IndexBuildsCoordinator::_scanCollectionAndInsertKeysIntoSorter(
+ OperationContext* opCtx,
+ const NamespaceStringOrUUID& dbAndUUID,
+ std::shared_ptr<ReplIndexBuildState> replState,
+ boost::optional<Lock::CollectionLock>* exclusiveCollectionLock) {
{
auto nss = CollectionCatalog::get(opCtx).lookupNSSByUUID(replState->collectionUUID);
@@ -1290,7 +1306,16 @@ void IndexBuildsCoordinator::_buildIndex(
log() << "Hanging after dumping inserts from bulk builder";
hangAfterIndexBuildDumpsInsertsFromBulk.pauseWhileSet();
}
+}
+/**
+ * Second phase is extracting the sorted keys and writing them into the new index table.
+ * Looks up collection namespace while holding locks.
+ */
+NamespaceString IndexBuildsCoordinator::_insertKeysFromSideTablesWithoutBlockingWrites(
+ OperationContext* opCtx,
+ const NamespaceStringOrUUID& dbAndUUID,
+ std::shared_ptr<ReplIndexBuildState> replState) {
// Perform the first drain while holding an intent lock.
{
opCtx->recoveryUnit()->abandonSnapshot();
@@ -1330,6 +1355,16 @@ void IndexBuildsCoordinator::_buildIndex(
hangAfterIndexBuildSecondDrain.pauseWhileSet();
}
+ return nss;
+}
+
+/**
+ * Waits for commit or abort signal from primary.
+ */
+Timestamp IndexBuildsCoordinator::_waitForCommitOrAbort(
+ OperationContext* opCtx,
+ const NamespaceString& nss,
+ std::shared_ptr<ReplIndexBuildState> replState) {
Timestamp commitIndexBuildTimestamp;
if (shouldWaitForCommitOrAbort(opCtx, nss, *replState)) {
log() << "Index build waiting for commit or abort before completing final phase: "
@@ -1361,7 +1396,20 @@ void IndexBuildsCoordinator::_buildIndex(
invariant(!replState->isCommitReady, replState->buildUUID.toString());
}
}
+ return commitIndexBuildTimestamp;
+}
+/**
+ * Third phase is catching up on all the writes that occurred during the first two phases.
+ * Accepts a commit timestamp for the index (null if not available).
+ */
+void IndexBuildsCoordinator::_insertKeysFromSideTablesAndCommit(
+ OperationContext* opCtx,
+ const NamespaceStringOrUUID& dbAndUUID,
+ std::shared_ptr<ReplIndexBuildState> replState,
+ const IndexBuildOptions& indexBuildOptions,
+ boost::optional<Lock::CollectionLock>* exclusiveCollectionLock,
+ const Timestamp& commitIndexBuildTimestamp) {
// Need to return the collection lock back to exclusive mode, to complete the index build.
opCtx->recoveryUnit()->abandonSnapshot();
exclusiveCollectionLock->emplace(opCtx, dbAndUUID, MODE_X);
diff --git a/src/mongo/db/index_builds_coordinator.h b/src/mongo/db/index_builds_coordinator.h
index 0cc29db2155..3c909c3f2c9 100644
--- a/src/mongo/db/index_builds_coordinator.h
+++ b/src/mongo/db/index_builds_coordinator.h
@@ -419,6 +419,55 @@ protected:
std::shared_ptr<ReplIndexBuildState> replState,
const IndexBuildOptions& indexBuildOptions,
boost::optional<Lock::CollectionLock>* collLock);
+
+ /**
+ * First phase is the collection scan and insertion of the keys into the sorter.
+ */
+ void _scanCollectionAndInsertKeysIntoSorter(
+ OperationContext* opCtx,
+ const NamespaceStringOrUUID& dbAndUUID,
+ std::shared_ptr<ReplIndexBuildState> replState,
+ boost::optional<Lock::CollectionLock>* exclusiveCollectionLock);
+
+ /**
+ * Second phase is extracting the sorted keys and writing them into the new index table.
+ * On completion, this function returns the namespace of the collection, which may have changed
+ * after the previous phase. The namespace is used in two phase index builds to determine the
+ * current replication state in _waitForCommitOrAbort().
+ */
+ NamespaceString _insertKeysFromSideTablesWithoutBlockingWrites(
+ OperationContext* opCtx,
+ const NamespaceStringOrUUID& dbAndUUID,
+ std::shared_ptr<ReplIndexBuildState> replState);
+
+ /**
+ * Waits for commit or abort signal from primary.
+ *
+ * On completion, this function returns a timestamp, which may be null, that may be used to
+ * update the mdb catalog as we commit the index build. The commit index build timestamp is
+ * obtained from a commitIndexBuild oplog entry during secondary oplog application.
+ * This function returns a null timestamp on receiving a abortIndexBuild oplog entry; or if we
+ * are currently a primary, in which case we do not need to wait any external signal to commit
+ * the index build.
+ */
+ Timestamp _waitForCommitOrAbort(OperationContext* opCtx,
+ const NamespaceString& nss,
+ std::shared_ptr<ReplIndexBuildState> replState);
+
+ /**
+ * Third phase is catching up on all the writes that occurred during the first two phases.
+ * Accepts a commit timestamp for the index, which could be null. See _waitForCommitOrAbort()
+ * comments. This timestamp is used only for committing the index, which sets the ready flag to
+ * true, to the catalog; it is not used for the catch-up writes during the final drain phase.
+ */
+ void _insertKeysFromSideTablesAndCommit(
+ OperationContext* opCtx,
+ const NamespaceStringOrUUID& dbAndUUID,
+ std::shared_ptr<ReplIndexBuildState> replState,
+ const IndexBuildOptions& indexBuildOptions,
+ boost::optional<Lock::CollectionLock>* exclusiveCollectionLock,
+ const Timestamp& commitIndexBuildTimestamp);
+
/**
* Returns total number of indexes in collection, including unfinished/in-progress indexes.
*