diff options
author | Rishab Joshi <rishab.joshi@mongodb.com> | 2022-05-29 07:50:23 +0000 |
---|---|---|
committer | Evergreen Agent <no-reply@evergreen.mongodb.com> | 2022-05-29 08:19:12 +0000 |
commit | b42b9f28708408fc8fbb03c7b0530148dc9d57dc (patch) | |
tree | 4c8968f598be3fe85864dbb137aed2cbec163fbb | |
parent | b154f8ea0332b8829f2c7f46a8ea84c2b86f3a45 (diff) | |
download | mongo-b42b9f28708408fc8fbb03c7b0530148dc9d57dc.tar.gz |
SERVER-66123 Introduce logic to write to the change collection in the primary.
-rw-r--r-- | jstests/replsets/write_change_stream_change_collection.js | 104 | ||||
-rw-r--r-- | src/mongo/db/catalog/collection_impl.cpp | 7 | ||||
-rw-r--r-- | src/mongo/db/catalog/validate_state.cpp | 4 | ||||
-rw-r--r-- | src/mongo/db/change_stream_change_collection_manager.cpp | 100 | ||||
-rw-r--r-- | src/mongo/db/change_stream_change_collection_manager.h | 23 | ||||
-rw-r--r-- | src/mongo/db/namespace_string.cpp | 9 | ||||
-rw-r--r-- | src/mongo/db/namespace_string.h | 7 | ||||
-rw-r--r-- | src/mongo/db/repl/SConscript | 1 | ||||
-rw-r--r-- | src/mongo/db/repl/collection_cloner.cpp | 6 | ||||
-rw-r--r-- | src/mongo/db/repl/oplog.cpp | 7 | ||||
-rw-r--r-- | src/mongo/db/repl/replication_coordinator_external_state_impl.cpp | 7 | ||||
-rw-r--r-- | src/mongo/db/storage/wiredtiger/wiredtiger_record_store.cpp | 3 | ||||
-rw-r--r-- | src/mongo/db/storage/wiredtiger/wiredtiger_record_store.h | 4 |
13 files changed, 238 insertions, 44 deletions
diff --git a/jstests/replsets/write_change_stream_change_collection.js b/jstests/replsets/write_change_stream_change_collection.js new file mode 100644 index 00000000000..32fce968ecc --- /dev/null +++ b/jstests/replsets/write_change_stream_change_collection.js @@ -0,0 +1,104 @@ +// Tests that entries are written to the change collection for collection create, drop and document +// modification operations. +// @tags: [ +// featureFlagServerlessChangeStreams, +// multiversion_incompatible, +// featureFlagMongoStore, +// ] +(function() { +"use strict"; + +const replSetTest = new ReplSetTest({nodes: 1}); +replSetTest.startSet({setParameter: "multitenancySupport=true"}); +replSetTest.initiate(); + +const primary = replSetTest.getPrimary(); +const oplogColl = primary.getDB("local").oplog.rs; +const changeColl = primary.getDB("config").system.change_collection; +const testDb = primary.getDB("test"); + +// Verifies that the oplog and change collection entries are the same for the specified start and +// end duration of the oplog timestamp. +function verifyChangeCollectionEntries(startOplogTimestamp, endOplogTimestamp) { + // Fetch all oplog and change collection entries for the duration: [startOplogTimestamp, + // endOplogTimestamp]. + const oplogEntries = + oplogColl.find({$and: [{ts: {$gte: startOplogTimestamp}}, {ts: {$lte: endOplogTimestamp}}]}) + .toArray(); + const changeCollectionEntries = + changeColl + .find({$and: [{_id: {$gte: startOplogTimestamp}}, {_id: {$lte: endOplogTimestamp}}]}) + .toArray(); + + assert.eq( + oplogEntries.length, + changeCollectionEntries.length, + "Number of entries in the oplog and the change collection is not the same. Oplog has total " + + oplogEntries.length + " entries , change collection has total " + + changeCollectionEntries.length + " entries"); + + for (let idx = 0; idx < oplogEntries.length; idx++) { + const oplogEntry = oplogEntries[idx]; + const changeCollectionEntry = changeCollectionEntries[idx]; + + // Remove the '_id' field from the change collection as oplog does not have it. + assert(changeCollectionEntry.hasOwnProperty("_id")); + assert.eq(timestampCmp(changeCollectionEntry._id, oplogEntry.ts), + 0, + "Change collection '_id' field: " + tojson(changeCollectionEntry._id) + + " is not same as the oplog 'ts' field: " + tojson(oplogEntry.ts)); + delete changeCollectionEntry["_id"]; + + // Verify that the oplog and change collecton entry (after removing the '_id') field are + // the same. + assert.eq( + oplogEntry, + changeCollectionEntry, + "Oplog and change collection entries are not same. Oplog entry: " + tojson(oplogEntry) + + ", change collection entry: " + tojson(changeCollectionEntry)); + } +} + +// Performs writes on the specified collection. +function performWrites(coll) { + const docIds = [1, 2, 3, 4, 5]; + docIds.forEach(docId => assert.commandWorked(coll.insert({_id: docId}))); + docIds.forEach( + docId => assert.commandWorked(coll.update({_id: docId}, {$set: {annotate: "updated"}}))); +} + +// Test the change collection entries with the oplog by performing some basic writes. +(function testBasicWritesInChangeCollection() { + const startOplogTimestamp = oplogColl.find().toArray().at(-1).ts; + assert(startOplogTimestamp != undefined); + + performWrites(testDb.stock); + assert(testDb.stock.drop()); + + const endOplogTimestamp = oplogColl.find().toArray().at(-1).ts; + assert(endOplogTimestamp !== undefined); + assert(timestampCmp(endOplogTimestamp, startOplogTimestamp) > 0); + + verifyChangeCollectionEntries(startOplogTimestamp, endOplogTimestamp); +})(); + +// Test the change collection entries with the oplog by performing writes in a transaction. +(function testWritesinChangeCollectionWithTrasactions() { + const startOplogTimestamp = oplogColl.find().toArray().at(-1).ts; + assert(startOplogTimestamp != undefined); + + const session = testDb.getMongo().startSession(); + const sessionDb = session.getDatabase(testDb.getName()); + session.startTransaction(); + performWrites(sessionDb.test); + session.commitTransaction_forTesting(); + + const endOplogTimestamp = oplogColl.find().toArray().at(-1).ts; + assert(endOplogTimestamp != undefined); + assert(timestampCmp(endOplogTimestamp, startOplogTimestamp) > 0); + + verifyChangeCollectionEntries(startOplogTimestamp, endOplogTimestamp); +})(); + +replSetTest.stopSet(); +}()); diff --git a/src/mongo/db/catalog/collection_impl.cpp b/src/mongo/db/catalog/collection_impl.cpp index a920e11d85c..ecb86d77238 100644 --- a/src/mongo/db/catalog/collection_impl.cpp +++ b/src/mongo/db/catalog/collection_impl.cpp @@ -1046,8 +1046,11 @@ Status CollectionImpl::_insertDocuments(OperationContext* opCtx, } } - opCtx->getServiceContext()->getOpObserver()->onInserts( - opCtx, ns(), uuid(), begin, end, fromMigrate); + // TODO SERVER-66813 fix issue with batch deletion. + if (!ns().isChangeCollection()) { + opCtx->getServiceContext()->getOpObserver()->onInserts( + opCtx, ns(), uuid(), begin, end, fromMigrate); + } _cappedDeleteAsNeeded(opCtx, records.begin()->id); diff --git a/src/mongo/db/catalog/validate_state.cpp b/src/mongo/db/catalog/validate_state.cpp index 88d66867751..09b597752cf 100644 --- a/src/mongo/db/catalog/validate_state.cpp +++ b/src/mongo/db/catalog/validate_state.cpp @@ -107,11 +107,13 @@ ValidateState::ValidateState(OperationContext* opCtx, bool ValidateState::shouldEnforceFastCount() const { if (_mode == ValidateMode::kForegroundFullEnforceFastCount) { - if (_nss.isOplog()) { + if (_nss.isOplog() || _nss.isChangeCollection()) { // Oplog writers only take a global IX lock, so the oplog can still be written to even // during full validation despite its collection X lock. This can cause validate to // incorrectly report an incorrect fast count on the oplog when run in enforceFastCount // mode. + // The oplog entries are also written to the change collections and are prone to fast + // count failures. return false; } else if (_nss == NamespaceString::kIndexBuildEntryNamespace) { // Do not enforce fast count on the 'config.system.indexBuilds' collection. This is an diff --git a/src/mongo/db/change_stream_change_collection_manager.cpp b/src/mongo/db/change_stream_change_collection_manager.cpp index e27c5af2af2..3311c7be092 100644 --- a/src/mongo/db/change_stream_change_collection_manager.cpp +++ b/src/mongo/db/change_stream_change_collection_manager.cpp @@ -37,13 +37,22 @@ #include "mongo/db/catalog/coll_mod.h" #include "mongo/db/catalog/create_collection.h" #include "mongo/db/catalog/drop_collection.h" +#include "mongo/db/catalog_raii.h" +#include "mongo/db/multitenancy_gen.h" #include "mongo/db/namespace_string.h" +#include "mongo/db/repl/oplog.h" #include "mongo/logv2/log.h" namespace mongo { namespace { const auto getChangeCollectionManager = ServiceContext::declareDecoration<boost::optional<ChangeStreamChangeCollectionManager>>(); + +// TODO: SERVER-65950 create or update the change collection for a particular tenant. +NamespaceString getTenantChangeCollectionNamespace(boost::optional<TenantId> tenantId) { + return NamespaceString{NamespaceString::kConfigDb, NamespaceString::kChangeCollectionName}; +} + } // namespace ChangeStreamChangeCollectionManager& ChangeStreamChangeCollectionManager::get( @@ -60,21 +69,24 @@ void ChangeStreamChangeCollectionManager::create(ServiceContext* service) { getChangeCollectionManager(service).emplace(service); } +bool ChangeStreamChangeCollectionManager::isChangeCollectionEnabled() { + return feature_flags::gFeatureFlagServerlessChangeStreams.isEnabled( + serverGlobalParams.featureCompatibility) && + gMultitenancySupport; +} + Status ChangeStreamChangeCollectionManager::createChangeCollection( OperationContext* opCtx, boost::optional<TenantId> tenantId) { - // TODO: SERVER-65950 create or update the change collection for a particular tenant. - const NamespaceString nss{NamespaceString::kConfigDb, - NamespaceString::kChangeStreamChangeCollection}; - // Make the change collection clustered by '_id'. The '_id' field will have the same value as // the 'ts' field of the oplog. CollectionOptions changeCollectionOptions; changeCollectionOptions.clusteredIndex.emplace(clustered_util::makeDefaultClusteredIdIndex()); changeCollectionOptions.capped = true; - auto status = createCollection(opCtx, nss, changeCollectionOptions, BSONObj()); + auto status = createCollection( + opCtx, getTenantChangeCollectionNamespace(tenantId), changeCollectionOptions, BSONObj()); if (status.code() == ErrorCodes::NamespaceExists) { - return Status(ErrorCodes::Error::OK, ""); + return Status::OK(); } return status; @@ -82,21 +94,75 @@ Status ChangeStreamChangeCollectionManager::createChangeCollection( Status ChangeStreamChangeCollectionManager::dropChangeCollection( OperationContext* opCtx, boost::optional<TenantId> tenantId) { - // TODO: SERVER-65950 remove the change collection for a particular tenant. - const NamespaceString nss{NamespaceString::kConfigDb, - NamespaceString::kChangeStreamChangeCollection}; DropReply dropReply; - return dropCollection( - opCtx, nss, &dropReply, DropCollectionSystemCollectionMode::kAllowSystemCollectionDrops); + return dropCollection(opCtx, + getTenantChangeCollectionNamespace(tenantId), + &dropReply, + DropCollectionSystemCollectionMode::kAllowSystemCollectionDrops); } -Status ChangeStreamChangeCollectionManager::insertDocumentsToChangeCollection( +void ChangeStreamChangeCollectionManager::insertDocumentsToChangeCollection( OperationContext* opCtx, - boost::optional<TenantId> tenantId, - std::vector<Record>* records, - const std::vector<Timestamp>& timestamps) { - // TODO SERVER-65210 add code to insert to the change collection in the primaries. - return Status(ErrorCodes::OK, ""); + const std::vector<Record>& oplogRecords, + const std::vector<Timestamp>& oplogTimestamps) { + invariant(oplogRecords.size() == oplogTimestamps.size()); + + // This method must be called within a 'WriteUnitOfWork'. The caller must be responsible for + // commiting the unit of work. + invariant(opCtx->lockState()->inAWriteUnitOfWork()); + + // Maps statements that should be inserted to the change collection for each tenant. + stdx::unordered_map<TenantId, std::vector<InsertStatement>, TenantId::Hasher> + tenantToInsertStatements; + + for (size_t idx = 0; idx < oplogRecords.size(); idx++) { + auto& record = oplogRecords[idx]; + auto& ts = oplogTimestamps[idx]; + + // Create a mutable document and update the '_id' field with the oplog entry timestamp. The + // '_id' field will be use to order the change collection documents. + Document oplogDoc(record.data.toBson()); + MutableDocument changeCollDoc(oplogDoc); + changeCollDoc["_id"] = Value(ts); + + // Create an insert statement that should be written at the timestamp 'ts' for a particular + // tenant. + auto readyChangeCollDoc = changeCollDoc.freeze(); + tenantToInsertStatements[TenantId::kSystemTenantId].push_back( + InsertStatement{readyChangeCollDoc.toBson(), ts, repl::OpTime::kUninitializedTerm}); + } + + for (auto&& [tenantId, insertStatements] : tenantToInsertStatements) { + // TODO SERVER-66715 avoid taking 'AutoGetCollection' and remove + // 'AllowLockAcquisitionOnTimestampedUnitOfWork'. + AllowLockAcquisitionOnTimestampedUnitOfWork allowLockAcquisition(opCtx->lockState()); + AutoGetCollection tenantChangeCollection( + opCtx, getTenantChangeCollectionNamespace(tenantId), LockMode::MODE_IX); + + // The change collection does not exist for a particular tenant because either the change + // collection is not enabled or is in the process of enablement. Ignore this insert for now. + // TODO: SERVER-65950 move this check before inserting to the map + // 'tenantToInsertStatements'. + if (!tenantChangeCollection) { + continue; + } + + // Writes to the change collection should not be replicated. + repl::UnreplicatedWritesBlock unReplBlock(opCtx); + + Status status = tenantChangeCollection->insertDocuments(opCtx, + insertStatements.begin(), + insertStatements.end(), + nullptr /* opDebug */, + false /* fromMigrate */); + if (!status.isOK()) { + LOGV2_FATAL(6612300, + "Write to change collection: {ns} failed: {error}", + "Write to change collection failed", + "ns"_attr = tenantChangeCollection->ns().toString(), + "error"_attr = status.toString()); + } + } } } // namespace mongo diff --git a/src/mongo/db/change_stream_change_collection_manager.h b/src/mongo/db/change_stream_change_collection_manager.h index b4ad0e25c50..8ecc48b9a5c 100644 --- a/src/mongo/db/change_stream_change_collection_manager.h +++ b/src/mongo/db/change_stream_change_collection_manager.h @@ -60,6 +60,12 @@ public: static ChangeStreamChangeCollectionManager& get(OperationContext* opCtx); /** + * Returns true if change collections are enabled for recording oplog entries, false + * otherwise. + */ + static bool isChangeCollectionEnabled(); + + /** * Creates a change collection for the specified tenant, if it doesn't exist. Returns Status::OK * if the change collection already exists. * @@ -75,16 +81,21 @@ public: Status dropChangeCollection(OperationContext* opCtx, boost::optional<TenantId> tenantId); /** - * Inserts documents to the change collection for the specified tenant. The parameter 'records' - * is a vector of oplog records and the parameter 'timestamps' is a vector for respective + * Inserts documents to change collections. The parameter 'oplogRecords' + * is a vector of oplog records and the parameter 'oplogTimestamps' is a vector for respective * timestamp for each oplog record. * + * The method fetches the tenant-id from the oplog entry, performs necessary modification to the + * document and then write to the tenant's change collection at the specified oplog timestamp. + * + * Failure in insertion to any change collection will result in a fatal exception and will bring + * down the node. + * * TODO: SERVER-65950 make tenantId field mandatory. */ - Status insertDocumentsToChangeCollection(OperationContext* opCtx, - boost::optional<TenantId> tenantId, - std::vector<Record>* records, - const std::vector<Timestamp>& timestamps); + void insertDocumentsToChangeCollection(OperationContext* opCtx, + const std::vector<Record>& oplogRecords, + const std::vector<Timestamp>& oplogTimestamps); }; } // namespace mongo diff --git a/src/mongo/db/namespace_string.cpp b/src/mongo/db/namespace_string.cpp index 525dd9c6724..d16370da310 100644 --- a/src/mongo/db/namespace_string.cpp +++ b/src/mongo/db/namespace_string.cpp @@ -243,7 +243,7 @@ bool NamespaceString::isLegalClientSystemNS( return true; } - if (isChangeStreamChangeCollection()) { + if (isChangeCollection()) { return true; } @@ -404,8 +404,8 @@ bool NamespaceString::isChangeStreamPreImagesCollection() const { return ns() == kChangeStreamPreImagesNamespace.ns(); } -bool NamespaceString::isChangeStreamChangeCollection() const { - return db() == kConfigDb && coll() == kChangeStreamChangeCollection; +bool NamespaceString::isChangeCollection() const { + return db() == kConfigDb && coll() == kChangeCollectionName; } bool NamespaceString::isConfigImagesCollection() const { @@ -432,8 +432,7 @@ NamespaceString NamespaceString::getTimeseriesViewNamespace() const { } bool NamespaceString::isImplicitlyReplicated() const { - if (isChangeStreamPreImagesCollection() || isConfigImagesCollection() || isChangeCollection() || - isChangeStreamChangeCollection()) { + if (isChangeStreamPreImagesCollection() || isConfigImagesCollection() || isChangeCollection()) { // Implicitly replicated namespaces are replicated, although they only replicate a subset of // writes. invariant(isReplicated()); diff --git a/src/mongo/db/namespace_string.h b/src/mongo/db/namespace_string.h index 687fb431bb1..dd6842974f0 100644 --- a/src/mongo/db/namespace_string.h +++ b/src/mongo/db/namespace_string.h @@ -77,7 +77,7 @@ public: static constexpr StringData kSystemDotViewsCollectionName = "system.views"_sd; // Name for the change stream change collection. - static constexpr StringData kChangeStreamChangeCollection = "system.change_collection"_sd; + static constexpr StringData kChangeCollectionName = "system.change_collection"_sd; // Names of privilege document collections static constexpr StringData kSystemUsers = "system.users"_sd; @@ -384,9 +384,6 @@ public: bool isSystemDotProfile() const { return coll() == "system.profile"; } - bool isChangeCollection() const { - return (db() == kConfigDb) && coll().startsWith("changes."); - } bool isSystemDotViews() const { return coll() == kSystemDotViewsCollectionName; } @@ -461,7 +458,7 @@ public: /** * Returns whether the specified namespace is config.system.changeCollection. */ - bool isChangeStreamChangeCollection() const; + bool isChangeCollection() const; /** * Returns whether the specified namespace is config.image_collection. diff --git a/src/mongo/db/repl/SConscript b/src/mongo/db/repl/SConscript index 3379a0d34d1..e9bcecfbdbf 100644 --- a/src/mongo/db/repl/SConscript +++ b/src/mongo/db/repl/SConscript @@ -73,6 +73,7 @@ env.Library( '$BUILD_DIR/mongo/db/catalog/index_build_oplog_entry', '$BUILD_DIR/mongo/db/catalog/local_oplog_info', '$BUILD_DIR/mongo/db/catalog/multi_index_block', + '$BUILD_DIR/mongo/db/change_stream_change_collection_manager', '$BUILD_DIR/mongo/db/commands/feature_compatibility_parsers', '$BUILD_DIR/mongo/db/concurrency/exception_util', '$BUILD_DIR/mongo/db/db_raii', diff --git a/src/mongo/db/repl/collection_cloner.cpp b/src/mongo/db/repl/collection_cloner.cpp index 8800297cb4d..bde00eef906 100644 --- a/src/mongo/db/repl/collection_cloner.cpp +++ b/src/mongo/db/repl/collection_cloner.cpp @@ -108,9 +108,9 @@ CollectionCloner::CollectionCloner(const NamespaceString& sourceNss, } BaseCloner::ClonerStages CollectionCloner::getStages() { - if (_sourceNss.isChangeStreamPreImagesCollection()) { - // Only the change stream pre-images collection needs to be created - its documents should - // not be copied. + if (_sourceNss.isChangeStreamPreImagesCollection() || _sourceNss.isChangeCollection()) { + // Only the change stream pre-images collection and change collection needs to be created - + // its documents should not be copied. return {&_listIndexesStage, &_createCollectionStage, &_setupIndexBuildersForUnfinishedIndexesStage}; diff --git a/src/mongo/db/repl/oplog.cpp b/src/mongo/db/repl/oplog.cpp index 7f521591c0c..0908b06213a 100644 --- a/src/mongo/db/repl/oplog.cpp +++ b/src/mongo/db/repl/oplog.cpp @@ -58,6 +58,7 @@ #include "mongo/db/catalog/local_oplog_info.h" #include "mongo/db/catalog/multi_index_block.h" #include "mongo/db/catalog/rename_collection.h" +#include "mongo/db/change_stream_change_collection_manager.h" #include "mongo/db/client.h" #include "mongo/db/coll_mod_gen.h" #include "mongo/db/commands.h" @@ -387,6 +388,12 @@ void _logOpsInner(OperationContext* opCtx, "error"_attr = result.toString()); } + // Insert the oplog records to the respective tenants change collections. + if (ChangeStreamChangeCollectionManager::isChangeCollectionEnabled()) { + ChangeStreamChangeCollectionManager::get(opCtx).insertDocumentsToChangeCollection( + opCtx, *records, timestamps); + } + // Set replCoord last optime only after we're sure the WUOW didn't abort and roll back. opCtx->recoveryUnit()->onCommit( [opCtx, replCoord, finalOpTime, wallTime](boost::optional<Timestamp> commitTime) { diff --git a/src/mongo/db/repl/replication_coordinator_external_state_impl.cpp b/src/mongo/db/repl/replication_coordinator_external_state_impl.cpp index 7ffa018a666..2266dfcfa38 100644 --- a/src/mongo/db/repl/replication_coordinator_external_state_impl.cpp +++ b/src/mongo/db/repl/replication_coordinator_external_state_impl.cpp @@ -560,10 +560,9 @@ OpTime ReplicationCoordinatorExternalStateImpl::onTransitionToPrimary(OperationC // TODO: SERVER-65948 move the change collection creation logic from here to the PM-2502 hooks. // The change collection will be created when the change stream is enabled. - if (::mongo::feature_flags::gFeatureFlagServerlessChangeStreams.isEnabled( - serverGlobalParams.featureCompatibility)) { - auto& changeCollectionManager = ChangeStreamChangeCollectionManager::get(opCtx); - auto status = changeCollectionManager.createChangeCollection(opCtx, boost::none); + if (ChangeStreamChangeCollectionManager::isChangeCollectionEnabled()) { + auto status = ChangeStreamChangeCollectionManager::get(opCtx).createChangeCollection( + opCtx, boost::none); if (!status.isOK()) { fassert(6520900, status); } diff --git a/src/mongo/db/storage/wiredtiger/wiredtiger_record_store.cpp b/src/mongo/db/storage/wiredtiger/wiredtiger_record_store.cpp index 337ee7e76b2..126f2631211 100644 --- a/src/mongo/db/storage/wiredtiger/wiredtiger_record_store.cpp +++ b/src/mongo/db/storage/wiredtiger/wiredtiger_record_store.cpp @@ -894,6 +894,7 @@ WiredTigerRecordStore::WiredTigerRecordStore(WiredTigerKVEngine* kvEngine, _isEphemeral(params.isEphemeral), _isLogged(params.isLogged), _isOplog(params.nss.isOplog()), + _isChangeCollection(params.nss.isChangeCollection()), _forceUpdateWithFullDocument(params.forceUpdateWithFullDocument), _oplogMaxSize(params.oplogMaxSize), _cappedCallback(params.cappedCallback), @@ -1416,7 +1417,7 @@ Status WiredTigerRecordStore::_insertRecords(OperationContext* opCtx, // Increment metrics for each insert separately, as opposed to outside of the loop. The API // requires that each record be accounted for separately. - if (!_isOplog) { + if (!_isOplog && !_isChangeCollection) { auto& metricsCollector = ResourceConsumption::MetricsCollector::get(opCtx); auto keyLength = computeRecordIdSize(record.id); diff --git a/src/mongo/db/storage/wiredtiger/wiredtiger_record_store.h b/src/mongo/db/storage/wiredtiger/wiredtiger_record_store.h index ff210ba87a2..3bb07432f71 100644 --- a/src/mongo/db/storage/wiredtiger/wiredtiger_record_store.h +++ b/src/mongo/db/storage/wiredtiger/wiredtiger_record_store.h @@ -340,6 +340,10 @@ private: const bool _isLogged; // True if the namespace of this record store starts with "local.oplog.", and false otherwise. const bool _isOplog; + // True if the namespace of this record store starts with "config.system.change_collection", and + // false otherwise. + const bool _isChangeCollection; + // TODO (SERVER-57482): Remove special handling of skipping "wiredtiger_calc_modify()". // True if force to update with the full document, and false otherwise. const bool _forceUpdateWithFullDocument; |