summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDan Larkin-York <dan.larkin-york@mongodb.com>2021-08-04 18:32:37 +0000
committerEvergreen Agent <no-reply@evergreen.mongodb.com>2021-08-04 18:58:29 +0000
commit940c7765a4abd748459225a91e045856a7e4607d (patch)
treee9903948a62032fb5c6eea8ef4c6cc528ffb467a
parentc1a2864de00a38c9c800218ca44c31088927de8b (diff)
downloadmongo-940c7765a4abd748459225a91e045856a7e4607d.tar.gz
SERVER-58392 Unpin durable history on rollback to refetch
-rw-r--r--src/mongo/db/repl/SConscript17
-rw-r--r--src/mongo/db/repl/replication_recovery.cpp9
-rw-r--r--src/mongo/db/repl/replication_recovery_test.cpp2
-rw-r--r--src/mongo/db/storage/durable_history_pin.cpp11
-rw-r--r--src/mongo/db/storage/durable_history_pin.h5
-rw-r--r--src/mongo/db/storage/wiredtiger/wiredtiger_kv_engine.cpp9
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,