summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAntonio Fuschetto <antonio.fuschetto@mongodb.com>2022-11-10 17:11:11 +0000
committerEvergreen Agent <no-reply@evergreen.mongodb.com>2022-11-10 17:38:11 +0000
commit1b3b0073a0b436a8a502b612f24fb2bd572772e5 (patch)
tree6d2fb59050d244596502e5b37526acb45c9263f4
parentec65af7e2185c7e266bc6a04ea7777eea713fa58 (diff)
downloadmongo-1b3b0073a0b436a8a502b612f24fb2bd572772e5.tar.gz
SERVER-70793 Make database metadata refresh first check new metadata under the IS lock before taking X lockr5.0.14-rc0r5.0.14
-rw-r--r--src/mongo/db/s/shard_filtering_metadata_refresh.cpp34
1 files changed, 34 insertions, 0 deletions
diff --git a/src/mongo/db/s/shard_filtering_metadata_refresh.cpp b/src/mongo/db/s/shard_filtering_metadata_refresh.cpp
index 55997b65ad0..2938a78867b 100644
--- a/src/mongo/db/s/shard_filtering_metadata_refresh.cpp
+++ b/src/mongo/db/s/shard_filtering_metadata_refresh.cpp
@@ -149,6 +149,40 @@ Status refreshDbMetadata(OperationContext* opCtx,
const auto swDbMetadata =
Grid::get(opCtx)->catalogCache()->getDatabaseWithRefresh(opCtx, dbName);
+ // Before setting the database metadata, exit early if the database version received by the
+ // config server is not newer than the cached one. This is a best-effort optimization to reduce
+ // the number of possible threads convoying on the exclusive lock below.
+ if (swDbMetadata.isOK()) {
+ Lock::DBLock dbLock(opCtx, dbName, MODE_IS);
+ auto* dss = DatabaseShardingState::get(opCtx, dbName);
+ auto dssLock = DatabaseShardingState::DSSLock::lockShared(opCtx, dss);
+
+ if (const auto cachedDbVersion = dss->getDbVersion(opCtx, dssLock)) {
+ const auto refreshedDbVersion = swDbMetadata.getValue().databaseVersion();
+
+ // Do not reorder these two statements! If the comparison is done through epochs, the
+ // construction order matters: we are pessimistically assuming that the refreshed
+ // version is newer when they have different UUIDs.
+ const ComparableDatabaseVersion comparableCachedDbVersion =
+ ComparableDatabaseVersion::makeComparableDatabaseVersion(cachedDbVersion);
+ const ComparableDatabaseVersion comparableRefreshedDbVersion =
+ ComparableDatabaseVersion::makeComparableDatabaseVersion(refreshedDbVersion);
+
+ if (comparableRefreshedDbVersion < comparableCachedDbVersion ||
+ (comparableRefreshedDbVersion == comparableCachedDbVersion &&
+ refreshedDbVersion.getTimestamp() == cachedDbVersion->getTimestamp())) {
+ LOGV2_DEBUG(7079300,
+ 2,
+ "Skip setting cached database metadata as there are no updates",
+ "db"_attr = dbName,
+ "cachedDbVersion"_attr = *cachedDbVersion,
+ "refreshedDbVersion"_attr = refreshedDbVersion);
+
+ return Status::OK();
+ }
+ }
+ }
+
Lock::DBLock dbLock(opCtx, dbName, MODE_X);
auto* dss = DatabaseShardingState::get(opCtx, dbName);
auto dssLock = DatabaseShardingState::DSSLock::lockExclusive(opCtx, dss);