summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMaria van Keulen <maria@mongodb.com>2018-04-24 14:38:23 -0400
committerMaria van Keulen <maria@mongodb.com>2018-04-30 13:45:28 -0400
commit7a2217a54d59c5d97e9e79cc40639c2589a18deb (patch)
tree306a50886114262a6f8efd42594e5ecbdb0f5bb1
parentcc7a103bd71ee98ad85e1b5dcca8763b4eb16679 (diff)
downloadmongo-7a2217a54d59c5d97e9e79cc40639c2589a18deb.tar.gz
SERVER-34482 Drop MMAP-specific system collections on wiredTiger
It is possible for a user to explicitly create MMAP-specific system collections when using wiredTiger. The presence of these collections may cause UUID checks to fail.
-rw-r--r--jstests/multiVersion/drop_mmap_system_collections_on_wt.js73
-rw-r--r--src/mongo/db/repair_database_and_check_version.cpp38
2 files changed, 106 insertions, 5 deletions
diff --git a/jstests/multiVersion/drop_mmap_system_collections_on_wt.js b/jstests/multiVersion/drop_mmap_system_collections_on_wt.js
new file mode 100644
index 00000000000..4335ef2650e
--- /dev/null
+++ b/jstests/multiVersion/drop_mmap_system_collections_on_wt.js
@@ -0,0 +1,73 @@
+// Ensure system.indexes created on wiredTiger 3.4 does not cause mongodb 4.0 to fail to start up
+// (see SERVER-34482). This test is to be removed after mongodb 4.0.
+(function() {
+ "use strict";
+
+ load("jstests/libs/feature_compatibility_version.js");
+ load("jstests/libs/check_uuids.js");
+ load("jstests/multiVersion/libs/multi_rs.js");
+
+ const UUIDCheckBinary = "latest";
+ const UUIDBinary = "3.6";
+ const noUUIDBinary = "3.4";
+ const systemIndexesDB = "systemIndexesDB";
+ const UUIDFCV = "3.6";
+
+ // Create system.indexes on wiredTiger, using a version of mongod that does not assign UUIDs.
+ let rst = new ReplSetTest({
+ nodes: 3,
+ nodeOptions: {binVersion: noUUIDBinary},
+ });
+ rst.startSet();
+ rst.initiate();
+ let primaryTestDB = rst.getPrimary().getDB(systemIndexesDB);
+ primaryTestDB.dropDatabase();
+ const systemIndexesColl = "system.indexes";
+ const createCmd = {create: systemIndexesColl, writeConcern: {w: "majority"}};
+ assert.commandWorked(primaryTestDB.runCommand(createCmd),
+ "expected " + tojson(createCmd) + " to succeed");
+ rst.awaitReplication();
+ assert(primaryTestDB.getCollectionInfos().length == 1);
+ assert(primaryTestDB.getCollectionInfos()[0].name == systemIndexesColl);
+ let secondaries = rst.getSecondaries();
+ for (let j = 0; j < secondaries.length; j++) {
+ let secondaryTestDB = secondaries[j].getDB(systemIndexesDB);
+ assert(secondaryTestDB.getCollectionInfos().length == 1);
+ assert(secondaryTestDB.getCollectionInfos()[0].name == systemIndexesColl);
+ }
+
+ // Restart with mongodb 3.6 and set the FCV to 3.6, which will assign UUIDs to all
+ // collections except for system.indexes and system.namespaces.
+ rst.upgradeSet({binVersion: UUIDBinary});
+
+ let primaryAdminDB = rst.getPrimary().getDB("admin");
+ assert.commandWorked(primaryAdminDB.runCommand({setFeatureCompatibilityVersion: UUIDFCV}));
+ rst.awaitReplication();
+ checkFCV(primaryAdminDB, UUIDFCV);
+ secondaries = rst.getSecondaries();
+ for (let j = 0; j < secondaries.length; j++) {
+ let secondaryAdminDB = secondaries[j].getDB("admin");
+ checkFCV(secondaryAdminDB, UUIDFCV);
+ }
+
+ primaryTestDB = rst.getPrimary().getDB(systemIndexesDB);
+ assert(!primaryTestDB.getCollectionInfos()[0].info.uuid);
+
+ // Restart with mongodb 4.0. This will drop system.indexes and system.namespaces if they
+ // exist, allowing the UUID check on start up to pass.
+ rst.upgradeSet({binVersion: UUIDCheckBinary});
+
+ primaryTestDB = rst.getPrimary().getDB(systemIndexesDB);
+ assert(primaryTestDB.getCollectionInfos().length == 0);
+
+ primaryAdminDB = rst.getPrimary().getDB("admin");
+ secondaries = rst.getSecondaries();
+ checkCollectionUUIDs(primaryAdminDB);
+ for (let j = 0; j < secondaries.length; j++) {
+ let secondaryTestDB = secondaries[j].getDB(systemIndexesDB);
+ assert(secondaryTestDB.getCollectionInfos().length == 0);
+ let secondaryAdminDB = secondaries[j].getDB("admin");
+ checkCollectionUUIDs(secondaryAdminDB);
+ }
+ rst.stopSet();
+})();
diff --git a/src/mongo/db/repair_database_and_check_version.cpp b/src/mongo/db/repair_database_and_check_version.cpp
index 37baffa3ab4..90f5872adc6 100644
--- a/src/mongo/db/repair_database_and_check_version.cpp
+++ b/src/mongo/db/repair_database_and_check_version.cpp
@@ -36,6 +36,7 @@
#include "mongo/db/catalog/database.h"
#include "mongo/db/catalog/database_catalog_entry.h"
#include "mongo/db/catalog/database_holder.h"
+#include "mongo/db/catalog/drop_collection.h"
#include "mongo/db/catalog/index_catalog.h"
#include "mongo/db/commands/feature_compatibility_version.h"
#include "mongo/db/commands/feature_compatibility_version_documentation.h"
@@ -50,6 +51,7 @@
#include "mongo/db/repl/replication_coordinator.h"
#include "mongo/db/server_options.h"
#include "mongo/db/storage/mmap_v1/mmap_v1_options.h"
+#include "mongo/util/exit.h"
#include "mongo/util/log.h"
#include "mongo/util/quick_exit.h"
#include "mongo/util/version.h"
@@ -140,14 +142,40 @@ Status ensureAllCollectionsHaveUUIDs(OperationContext* opCtx,
invariant(db);
for (auto collectionIt = db->begin(); collectionIt != db->end(); ++collectionIt) {
Collection* coll = *collectionIt;
- if (!coll->uuid()) {
- // system.indexes and system.namespaces don't currently have UUIDs in MMAP.
- // SERVER-29926 and SERVER-30095 will address this problem.
- if (isMmapV1 && (coll->ns().coll() == "system.indexes" ||
- coll->ns().coll() == "system.namespaces")) {
+ // The presence of system.indexes or system.namespaces on wiredTiger may
+ // have undesirable results (see SERVER-32894, SERVER-34482). It is okay to
+ // drop these collections on wiredTiger because users are not permitted to
+ // store data in them.
+ if (coll->ns().coll() == "system.indexes" || coll->ns().coll() == "system.namespaces") {
+ if (isMmapV1) {
+ // system.indexes and system.namespaces don't currently have UUIDs in MMAP.
+ // SERVER-29926 and SERVER-30095 will address this problem.
continue;
}
+ const auto nssToDrop = coll->ns();
+ LOG(1) << "Attempting to drop invalid system collection " << nssToDrop;
+ if (coll->numRecords(opCtx)) {
+ severe(LogComponent::kControl) << "Cannot drop non-empty collection "
+ << nssToDrop.ns();
+ exitCleanly(EXIT_NEED_DOWNGRADE);
+ }
+ repl::UnreplicatedWritesBlock uwb(opCtx);
+ writeConflictRetry(opCtx, "dropSystemIndexes", nssToDrop.ns(), [&] {
+ WriteUnitOfWork wunit(opCtx);
+ BSONObjBuilder unusedResult;
+ fassert(50837,
+ dropCollection(
+ opCtx,
+ nssToDrop,
+ unusedResult,
+ {},
+ DropCollectionSystemCollectionMode::kAllowSystemCollectionDrops));
+ wunit.commit();
+ });
+ continue;
+ }
+ if (!coll->uuid()) {
if (!coll->ns().isReplicated()) {
nonReplicatedCollNSSsWithoutUUIDs.push_back(coll->ns());
continue;