diff options
author | Dan Larkin-York <dan.larkin-york@mongodb.com> | 2021-08-04 18:32:37 +0000 |
---|---|---|
committer | Evergreen Agent <no-reply@evergreen.mongodb.com> | 2021-08-04 18:58:29 +0000 |
commit | 940c7765a4abd748459225a91e045856a7e4607d (patch) | |
tree | e9903948a62032fb5c6eea8ef4c6cc528ffb467a | |
parent | c1a2864de00a38c9c800218ca44c31088927de8b (diff) | |
download | mongo-940c7765a4abd748459225a91e045856a7e4607d.tar.gz |
SERVER-58392 Unpin durable history on rollback to refetch
-rw-r--r-- | src/mongo/db/repl/SConscript | 17 | ||||
-rw-r--r-- | src/mongo/db/repl/replication_recovery.cpp | 9 | ||||
-rw-r--r-- | src/mongo/db/repl/replication_recovery_test.cpp | 2 | ||||
-rw-r--r-- | src/mongo/db/storage/durable_history_pin.cpp | 11 | ||||
-rw-r--r-- | src/mongo/db/storage/durable_history_pin.h | 5 | ||||
-rw-r--r-- | src/mongo/db/storage/wiredtiger/wiredtiger_kv_engine.cpp | 9 |
6 files changed, 41 insertions, 12 deletions
diff --git a/src/mongo/db/repl/SConscript b/src/mongo/db/repl/SConscript index 88c49da1d7f..ed47b9c0440 100644 --- a/src/mongo/db/repl/SConscript +++ b/src/mongo/db/repl/SConscript @@ -273,6 +273,7 @@ env.Library( LIBDEPS_PRIVATE=[ '$BUILD_DIR/mongo/base', '$BUILD_DIR/mongo/db/storage/journal_flusher', + '$BUILD_DIR/mongo/db/storage/storage_control', '$BUILD_DIR/mongo/db/storage/storage_options', 'oplog', 'oplog_application', @@ -314,7 +315,7 @@ env.Library( source=[ 'scatter_gather_algorithm.cpp', 'scatter_gather_runner.cpp', - ], + ], LIBDEPS=[ '$BUILD_DIR/mongo/executor/task_executor_interface', ], @@ -816,7 +817,7 @@ env.Library( 'member_config.idl', 'repl_set_config.idl', 'repl_set_config_params.idl', - ], + ], LIBDEPS=[ '$BUILD_DIR/mongo/base', '$BUILD_DIR/mongo/bson/util/bson_extract', @@ -967,7 +968,7 @@ env.Library( 'database_cloner.cpp', 'initial_sync_base_cloner.cpp', ], - LIBDEPS = [ + LIBDEPS=[ '$BUILD_DIR/mongo/base', '$BUILD_DIR/mongo/client/clientdriver_network', '$BUILD_DIR/mongo/util/concurrency/thread_pool', @@ -997,7 +998,7 @@ env.Library( 'tenant_database_cloner.cpp', 'tenant_base_cloner.cpp', ], - LIBDEPS = [ + LIBDEPS=[ '$BUILD_DIR/mongo/base', '$BUILD_DIR/mongo/db/dbdirectclient', 'base_cloner', @@ -1248,7 +1249,7 @@ env.Library( env.Library( target='tenant_migration_errors', - source= [ + source=[ 'tenant_migration_conflict_info.cpp', ], LIBDEPS=[ @@ -1313,7 +1314,7 @@ env.Library( env.Library( target='tenant_migration_recipient_service', - source= [ + source=[ 'tenant_migration_recipient_service.cpp', ], LIBDEPS=[ @@ -1607,6 +1608,7 @@ if wiredtiger: '$BUILD_DIR/mongo/db/service_context_test_fixture', '$BUILD_DIR/mongo/db/stats/counters', '$BUILD_DIR/mongo/db/storage/ephemeral_for_test/storage_ephemeral_for_test_core', + '$BUILD_DIR/mongo/db/storage/storage_control', '$BUILD_DIR/mongo/db/transaction', '$BUILD_DIR/mongo/db/update/update_test_helpers', '$BUILD_DIR/mongo/dbtests/mocklib', @@ -1721,7 +1723,8 @@ env.CppUnitTest( 'tenant_cloner_test_fixture.cpp', ], LIBDEPS=[ - '$BUILD_DIR/mongo/db/auth/authmocks', # Required for service context test fixture + # Required for service context test fixture + '$BUILD_DIR/mongo/db/auth/authmocks', '$BUILD_DIR/mongo/db/catalog/collection_options', '$BUILD_DIR/mongo/db/service_context_d_test_fixture', '$BUILD_DIR/mongo/dbtests/mocklib', diff --git a/src/mongo/db/repl/replication_recovery.cpp b/src/mongo/db/repl/replication_recovery.cpp index e4f49e5c132..2af2027aaec 100644 --- a/src/mongo/db/repl/replication_recovery.cpp +++ b/src/mongo/db/repl/replication_recovery.cpp @@ -51,6 +51,7 @@ #include "mongo/db/server_recovery.h" #include "mongo/db/session.h" #include "mongo/db/storage/control/journal_flusher.h" +#include "mongo/db/storage/durable_history_pin.h" #include "mongo/db/storage/storage_parameters_gen.h" #include "mongo/db/transaction_history_iterator.h" #include "mongo/db/transaction_participant.h" @@ -551,13 +552,19 @@ void ReplicationRecoveryImpl::_recoverFromUnstableCheckpoint(OperationContext* o // When `recoverFromOplog` truncates the oplog, that also happens to set the "oldest // timestamp" to the truncation point[1]. `_applyToEndOfOplog` will then perform writes // before the truncation point. Doing so violates the constraint that all updates must be - // timestamped newer than the "oldest timestamp". This call will move the "oldest + // timestamped newer than the "oldest timestamp". So we will need to move the "oldest // timestamp" back to the `startPoint`. // + // Before doing so, we will remove any pins. Forcing the oldest timestamp backwards will + // error if there are pins in place, as those pin requests will no longer be satisfied. + // Recovering from an unstable checkpoint has no history in the first place. Thus, clearing + // pins has no real effect on history being held. + // // [1] This is arguably incorrect. On rollback for nodes that are not keeping history to // the "majority point", the "oldest timestamp" likely needs to go back in time. The // oplog's `cappedTruncateAfter` method was a convenient location for this logic, which, // unfortunately, conflicts with the usage above. + DurableHistoryRegistry::get(opCtx->getServiceContext())->clearPins(opCtx); opCtx->getServiceContext()->getStorageEngine()->setOldestTimestamp( appliedThrough.getTimestamp()); diff --git a/src/mongo/db/repl/replication_recovery_test.cpp b/src/mongo/db/repl/replication_recovery_test.cpp index 742313ddae1..e3818a07c71 100644 --- a/src/mongo/db/repl/replication_recovery_test.cpp +++ b/src/mongo/db/repl/replication_recovery_test.cpp @@ -50,6 +50,7 @@ #include "mongo/db/service_context_d_test_fixture.h" #include "mongo/db/session_catalog_mongod.h" #include "mongo/db/session_txn_record_gen.h" +#include "mongo/db/storage/durable_history_pin.h" #include "mongo/db/storage/storage_options.h" #include "mongo/db/storage/storage_parameters_gen.h" #include "mongo/db/transaction_participant.h" @@ -188,6 +189,7 @@ private: auto service = getServiceContext(); StorageInterface::set(service, std::make_unique<StorageInterfaceRecovery>()); _storageInterface = static_cast<StorageInterfaceRecovery*>(StorageInterface::get(service)); + DurableHistoryRegistry::set(service, std::make_unique<DurableHistoryRegistry>()); _createOpCtx(); _consistencyMarkers = std::make_unique<ReplicationConsistencyMarkersMock>(); diff --git a/src/mongo/db/storage/durable_history_pin.cpp b/src/mongo/db/storage/durable_history_pin.cpp index 09e4e97bcd4..cc1d0c10c9a 100644 --- a/src/mongo/db/storage/durable_history_pin.cpp +++ b/src/mongo/db/storage/durable_history_pin.cpp @@ -101,4 +101,15 @@ void DurableHistoryRegistry::reconcilePins(OperationContext* opCtx) { } } +void DurableHistoryRegistry::clearPins(OperationContext* opCtx) { + StorageEngine* engine = opCtx->getServiceContext()->getStorageEngine(); + if (!engine->supportsRecoveryTimestamp()) { + return; + } + + for (auto& pin : _pins) { + engine->unpinOldestTimestamp(pin->getName()); + } +} + } // namespace mongo diff --git a/src/mongo/db/storage/durable_history_pin.h b/src/mongo/db/storage/durable_history_pin.h index 0a202772579..e50ed11944e 100644 --- a/src/mongo/db/storage/durable_history_pin.h +++ b/src/mongo/db/storage/durable_history_pin.h @@ -75,6 +75,11 @@ public: */ void reconcilePins(OperationContext* opCtx); + /** + * Removes all registered pins. + */ + void clearPins(OperationContext* opCtx); + private: std::vector<std::unique_ptr<DurableHistoryPin>> _pins; }; diff --git a/src/mongo/db/storage/wiredtiger/wiredtiger_kv_engine.cpp b/src/mongo/db/storage/wiredtiger/wiredtiger_kv_engine.cpp index bdc58ff901a..28a0212f967 100644 --- a/src/mongo/db/storage/wiredtiger/wiredtiger_kv_engine.cpp +++ b/src/mongo/db/storage/wiredtiger/wiredtiger_kv_engine.cpp @@ -2072,10 +2072,11 @@ void WiredTigerKVEngine::setOldestTimestamp(Timestamp newOldestTimestamp, bool f } if (force) { - // Forcing the oldest timestamp backwards (e.g: eMRC=off rollback) to a value of T - // invalidates all snapshots > T. Components that register a pinned timestamp must - // synchronize with events that invalidate their snapshots, unpin themselves and either - // fail themselves, or reacquire a new snapshot after the rollback event. + // The oldest timestamp should only be forced backwards during replication recovery in order + // to do rollback via refetch. This refetching process invalidates any timestamped snapshots + // until after it completes. Components that register a pinned timestamp must synchronize + // with events that invalidate their snapshots, unpin themselves and either fail themselves, + // or reacquire a new snapshot after the rollback event. // // Forcing the oldest timestamp forward -- potentially past a pin request raises the // question of whether the pin should be honored. For now we will invariant there is no pin, |