summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorLingzhi Deng <lingzhi.deng@mongodb.com>2020-11-04 13:53:57 -0500
committerLingzhi Deng <lingzhi.deng@mongodb.com>2020-11-04 13:53:57 -0500
commit2b0d78e836ff4c4ed08212c49e93a02fc20ca669 (patch)
tree6ae234207ef3f43ab08c3c401ea3ab30f23157d8
parentf3699db3cf64566a0f87a84cdf9d2f26a6ebff73 (diff)
downloadmongo-2b0d78e836ff4c4ed08212c49e93a02fc20ca669.tar.gz
SERVER-52617: Cache the pointer to the oplog collection before running recoverToOplogTimestamp
-rw-r--r--jstests/replsets/standalone_recover_to_oplog_timestamp.js54
-rw-r--r--src/mongo/db/repl/SConscript1
-rw-r--r--src/mongo/db/repl/local_oplog_info.cpp4
-rw-r--r--src/mongo/db/repl/replication_recovery.cpp3
4 files changed, 61 insertions, 1 deletions
diff --git a/jstests/replsets/standalone_recover_to_oplog_timestamp.js b/jstests/replsets/standalone_recover_to_oplog_timestamp.js
new file mode 100644
index 00000000000..b675eb72add
--- /dev/null
+++ b/jstests/replsets/standalone_recover_to_oplog_timestamp.js
@@ -0,0 +1,54 @@
+/**
+ * Test replication recovery as standalone with 'recoverToOplogTimestamp' in read-only mode
+ * (i.e. queryableBackupMode).
+ *
+ * @tags: [
+ * requires_majority_read_concern,
+ * requires_persistence,
+ * requires_replication,
+ * requires_wiredtiger,
+ * ]
+ */
+
+(function() {
+"use strict";
+
+const dbName = "test";
+const collName = "foo";
+
+const rst = new ReplSetTest({nodes: 1});
+rst.startSet();
+rst.initiateWithHighElectionTimeout();
+const primary = rst.getPrimary();
+const primaryDB = primary.getDB(dbName);
+
+const recoveryTimestamp = assert.commandWorked(primaryDB.runCommand({ping: 1})).operationTime;
+
+// Hold back the recovery timestamp before doing another write so we have some oplog entries to
+// apply when restart in queryableBackupMode with recoverToOplogTimestamp.
+assert.commandWorked(primaryDB.adminCommand({
+ "configureFailPoint": 'holdStableTimestampAtSpecificTimestamp',
+ "mode": 'alwaysOn',
+ "data": {"timestamp": recoveryTimestamp}
+}));
+
+const docs = [{_id: 1}];
+const operationTime =
+ assert.commandWorked(primaryDB.runCommand({insert: collName, documents: docs})).operationTime;
+
+rst.stopSet(/*signal=*/null, /*forRestart=*/true);
+
+// Restart as standalone in queryableBackupMode and run replication recovery up to the last insert.
+const primaryStandalone = MongoRunner.runMongod({
+ dbpath: primary.dbpath,
+ noReplSet: true,
+ noCleanData: true,
+ setParameter: {recoverToOplogTimestamp: tojson({timestamp: operationTime})},
+ queryableBackupMode: ""
+});
+
+// Test that the last insert is visible after replication recovery.
+assert.eq(primaryStandalone.getDB(dbName)[collName].find().toArray(), docs);
+
+MongoRunner.stopMongod(primaryStandalone);
+}());
diff --git a/src/mongo/db/repl/SConscript b/src/mongo/db/repl/SConscript
index 4b9526e735e..14ec068392b 100644
--- a/src/mongo/db/repl/SConscript
+++ b/src/mongo/db/repl/SConscript
@@ -25,6 +25,7 @@ env.Library(
'repl_coordinator_interface',
'$BUILD_DIR/mongo/db/logical_clock',
'$BUILD_DIR/mongo/db/logical_time',
+ '$BUILD_DIR/mongo/db/mongod_options',
'$BUILD_DIR/mongo/db/storage/flow_control',
],
)
diff --git a/src/mongo/db/repl/local_oplog_info.cpp b/src/mongo/db/repl/local_oplog_info.cpp
index f6573c6a5f8..2b5ed06bab5 100644
--- a/src/mongo/db/repl/local_oplog_info.cpp
+++ b/src/mongo/db/repl/local_oplog_info.cpp
@@ -35,6 +35,7 @@
#include "mongo/db/logical_clock.h"
#include "mongo/db/logical_time.h"
+#include "mongo/db/mongod_options_storage_gen.h"
#include "mongo/db/repl/replication_coordinator.h"
#include "mongo/db/storage/flow_control.h"
#include "mongo/db/storage/record_store.h"
@@ -74,7 +75,8 @@ void LocalOplogInfo::setOplogCollectionName(ServiceContext* service) {
_oplogName = NamespaceString::kRsOplogNamespace;
break;
case ReplicationCoordinator::modeNone:
- if (ReplSettings::shouldRecoverFromOplogAsStandalone()) {
+ if (ReplSettings::shouldRecoverFromOplogAsStandalone() ||
+ (storageGlobalParams.readOnly && !recoverToOplogTimestamp.empty())) {
_oplogName = NamespaceString::kRsOplogNamespace;
}
// leave empty otherwise.
diff --git a/src/mongo/db/repl/replication_recovery.cpp b/src/mongo/db/repl/replication_recovery.cpp
index 29f0717fc98..b1dc2e86946 100644
--- a/src/mongo/db/repl/replication_recovery.cpp
+++ b/src/mongo/db/repl/replication_recovery.cpp
@@ -359,6 +359,9 @@ void ReplicationRecoveryImpl::recoverFromOplogUpTo(OperationContext* opCtx, Time
"Cannot use 'recoverToOplogTimestamp' without a stable checkpoint");
}
+ // Initialize the cached pointer to the oplog collection.
+ acquireOplogCollectionForLogging(opCtx);
+
// This may take an IS lock on the oplog collection.
_truncateOplogIfNeededAndThenClearOplogTruncateAfterPoint(opCtx, recoveryTS);