diff options
author | Lingzhi Deng <lingzhi.deng@mongodb.com> | 2020-11-04 13:53:57 -0500 |
---|---|---|
committer | Lingzhi Deng <lingzhi.deng@mongodb.com> | 2020-11-04 13:53:57 -0500 |
commit | 2b0d78e836ff4c4ed08212c49e93a02fc20ca669 (patch) | |
tree | 6ae234207ef3f43ab08c3c401ea3ab30f23157d8 | |
parent | f3699db3cf64566a0f87a84cdf9d2f26a6ebff73 (diff) | |
download | mongo-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.js | 54 | ||||
-rw-r--r-- | src/mongo/db/repl/SConscript | 1 | ||||
-rw-r--r-- | src/mongo/db/repl/local_oplog_info.cpp | 4 | ||||
-rw-r--r-- | src/mongo/db/repl/replication_recovery.cpp | 3 |
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); |