summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorEnrico <enrico.golfieri@mongodb.com>2023-04-21 14:21:02 +0000
committerEvergreen Agent <no-reply@evergreen.mongodb.com>2023-04-21 14:42:33 +0000
commit2f5665769c421ed8641c7ddf360c541655337735 (patch)
treeda91d836fae2298dd740c02c42ab1c0d88637b42
parent151cfa0038a81b950408b585a60d7503cf9c1ef1 (diff)
downloadmongo-2f5665769c421ed8641c7ddf360c541655337735.tar.gz
SERVER-73390 Mitigate database version regression bug on drop database ( cherry picked from 5780b40e0adf02427b5718f12959eae7d5e72939 )
-rw-r--r--src/mongo/db/s/drop_database_coordinator.cpp43
1 files changed, 31 insertions, 12 deletions
diff --git a/src/mongo/db/s/drop_database_coordinator.cpp b/src/mongo/db/s/drop_database_coordinator.cpp
index 660a95b96cc..faadd47bfba 100644
--- a/src/mongo/db/s/drop_database_coordinator.cpp
+++ b/src/mongo/db/s/drop_database_coordinator.cpp
@@ -101,6 +101,25 @@ private:
const BSONObj _reason;
};
+bool isDbAlreadyDropped(OperationContext* opCtx,
+ const boost::optional<mongo::DatabaseVersion>& dbVersion,
+ const StringData& dbName) {
+ if (dbVersion) {
+ try {
+ auto const catalogClient = Grid::get(opCtx)->catalogClient();
+ const auto db = catalogClient->getDatabase(
+ opCtx, dbName, repl::ReadConcernLevel::kMajorityReadConcern);
+ if (dbVersion->getUuid() != db.getVersion().getUuid()) {
+ // The database was dropped and re-created with a different UUID
+ return true;
+ }
+ } catch (const ExceptionFor<ErrorCodes::NamespaceNotFound>&) {
+ // The database was already dropped
+ return true;
+ }
+ }
+ return false;
+}
} // namespace
@@ -264,18 +283,18 @@ ExecutorFuture<void> DropDatabaseCoordinator::_runImpl(
sharding_ddl_util::performNoopMajorityWriteLocally(opCtx);
// ensure we do not delete collections of a different DB
- if (!_firstExecution && _doc.getDatabaseVersion()) {
- try {
- const auto db = catalogClient->getDatabase(
- opCtx, _dbName, repl::ReadConcernLevel::kMajorityReadConcern);
- if (_doc.getDatabaseVersion()->getUuid() != db.getVersion().getUuid()) {
- VectorClockMutable::get(opCtx)->waitForDurableConfigTime().get(opCtx);
- return; // skip to _flushDatabaseCacheUpdates
- }
- } catch (const ExceptionFor<ErrorCodes::NamespaceNotFound>&) {
- VectorClockMutable::get(opCtx)->waitForDurableConfigTime().get(opCtx);
- return; // skip to _flushDatabaseCacheUpdates
- }
+ if (!_firstExecution &&
+ isDbAlreadyDropped(opCtx, _doc.getDatabaseVersion(), _dbName)) {
+ // Clear the database sharding state so that all subsequent write operations
+ // with the old database version will fail due to StaleDbVersion.
+ // Note: because we are using an scoped critical section it could happen that
+ // the dbversion being deleted is recovered once we return. It is a rare
+ // occurence, but it might lead to a situation where the now former primary
+ // will believe to still be primary.
+ _clearDatabaseInfoOnPrimary(opCtx);
+ _clearDatabaseInfoOnSecondaries(opCtx);
+ VectorClockMutable::get(opCtx)->waitForDurableConfigTime().get(opCtx);
+ return; // skip to FlushDatabaseCacheUpdates
}
if (_doc.getCollInfo()) {