From 6acc65f52de00bd9caa45e582e65a8669424b4dc Mon Sep 17 00:00:00 2001 From: Antonio Fuschetto Date: Mon, 29 Aug 2022 08:06:59 +0000 Subject: SERVER-69108 SCCL can immediately return config and admin metadata without triggering a refresh --- jstests/sharding/append_oplog_note_mongos.js | 5 --- .../db/s/flush_database_cache_updates_command.cpp | 44 ++++++++++++++++++++++ .../db/s/shard_filtering_metadata_refresh.cpp | 4 ++ .../db/s/shard_server_catalog_cache_loader.cpp | 6 +++ 4 files changed, 54 insertions(+), 5 deletions(-) diff --git a/jstests/sharding/append_oplog_note_mongos.js b/jstests/sharding/append_oplog_note_mongos.js index 641ccf25c2b..1369ecb06be 100644 --- a/jstests/sharding/append_oplog_note_mongos.js +++ b/jstests/sharding/append_oplog_note_mongos.js @@ -41,11 +41,6 @@ assert(res.hasOwnProperty("raw"), res); appendOplogNoteFailpoint.wait(); appendOplogNoteFailpoint.off(); -// Force a database refresh on the sharding side so that the corresponding config.cache.databases -// entry is already in the oplog before we start issuing successful appendOplogNote commands. -assert.commandWorked(shardOnePrimary.adminCommand({_flushDatabaseCacheUpdates: "config"})); -assert.commandWorked(shardTwoPrimary.adminCommand({_flushDatabaseCacheUpdates: "config"})); - // Test that a successful 'appendOplogNote' command performs a no-op write and advances the // $clusterTime. const shardOneBefore = diff --git a/src/mongo/db/s/flush_database_cache_updates_command.cpp b/src/mongo/db/s/flush_database_cache_updates_command.cpp index e3a857fd57d..ff4837fdf16 100644 --- a/src/mongo/db/s/flush_database_cache_updates_command.cpp +++ b/src/mongo/db/s/flush_database_cache_updates_command.cpp @@ -37,6 +37,8 @@ #include "mongo/db/catalog_raii.h" #include "mongo/db/client.h" #include "mongo/db/commands.h" +#include "mongo/db/database_name.h" +#include "mongo/db/dbdirectclient.h" #include "mongo/db/operation_context.h" #include "mongo/db/repl/repl_client_info.h" #include "mongo/db/s/database_sharding_state.h" @@ -54,6 +56,28 @@ namespace mongo { namespace { +/** + * Inserts a database collection entry with fixed metadata for the `config` or `admin` database. If + * the entry key already exists, it's not updated. + */ +Status insertDatabaseEntryForBackwardCompatibility(OperationContext* opCtx, + const DatabaseName& dbName) { + invariant(dbName == NamespaceString::kAdminDb || dbName == NamespaceString::kConfigDb); + + DBDirectClient client(opCtx); + auto commandResponse = client.runCommand([&] { + auto dbMetadata = + DatabaseType(dbName.toString(), ShardId::kConfigServerId, DatabaseVersion::makeFixed()); + + write_ops::InsertCommandRequest insertOp(NamespaceString::kShardConfigDatabasesNamespace); + insertOp.setDocuments({dbMetadata.toBSON()}); + return insertOp.serialize({}); + }()); + + auto commandStatus = getStatusFromWriteCommandReply(commandResponse->getCommandReply()); + return commandStatus.code() == ErrorCodes::DuplicateKey ? Status::OK() : commandStatus; +} + template class FlushDatabaseCacheUpdatesCmdBase : public TypedCommand { public: @@ -119,6 +143,26 @@ public: "Can't call _flushDatabaseCacheUpdates if in read-only mode", !opCtx->readOnly()); + if (_dbName() == NamespaceString::kAdminDb || _dbName() == NamespaceString::kConfigDb) { + // The admin and config databases have fixed metadata that does not need to be + // refreshed. + + if (Base::request().getSyncFromConfig()) { + // To ensure compatibility with old secondaries that still call the + // _flushDatabaseCacheUpdates command to get updated database metadata from + // primary, an entry with fixed metadata is inserted in the + // config.cache.databases collection. + + LOGV2_DEBUG(6910800, + 1, + "Inserting a database collection entry with fixed metadata", + "db"_attr = _dbName()); + uassertStatusOK(insertDatabaseEntryForBackwardCompatibility(opCtx, _dbName())); + } + + return; + } + boost::optional> criticalSectionSignal; { diff --git a/src/mongo/db/s/shard_filtering_metadata_refresh.cpp b/src/mongo/db/s/shard_filtering_metadata_refresh.cpp index 5debd090ab2..bcb67504217 100644 --- a/src/mongo/db/s/shard_filtering_metadata_refresh.cpp +++ b/src/mongo/db/s/shard_filtering_metadata_refresh.cpp @@ -65,6 +65,10 @@ void onDbVersionMismatch(OperationContext* opCtx, invariant(!opCtx->getClient()->isInDirectClient()); invariant(ShardingState::get(opCtx)->canAcceptShardedCommands()); + tassert(ErrorCodes::IllegalOperation, + "Can't check version of {} database"_format(dbName), + dbName != NamespaceString::kAdminDb && dbName != NamespaceString::kConfigDb); + Timer t{}; ScopeGuard finishTiming([&] { CurOp::get(opCtx)->debug().databaseVersionRefreshMillis += Milliseconds(t.millis()); diff --git a/src/mongo/db/s/shard_server_catalog_cache_loader.cpp b/src/mongo/db/s/shard_server_catalog_cache_loader.cpp index 22e0710f6d3..cbc44c21b03 100644 --- a/src/mongo/db/s/shard_server_catalog_cache_loader.cpp +++ b/src/mongo/db/s/shard_server_catalog_cache_loader.cpp @@ -456,6 +456,12 @@ SemiFuture ShardServerCatalogCacheLoader::getChunksS } SemiFuture ShardServerCatalogCacheLoader::getDatabase(StringData dbName) { + // The admin and config database have fixed metadata that does not need to be refreshed. + if (dbName == NamespaceString::kAdminDb || dbName == NamespaceString::kConfigDb) { + return DatabaseType( + dbName.toString(), ShardId::kConfigServerId, DatabaseVersion::makeFixed()); + } + const auto [isPrimary, term] = [&] { stdx::lock_guard lock(_mutex); return std::make_tuple(_role == ReplicaSetRole::Primary, _term); -- cgit v1.2.1