summaryrefslogtreecommitdiff
path: root/src/mongo/db/repl/oplog.cpp
diff options
context:
space:
mode:
authorDaniel Gottlieb <daniel.gottlieb@mongodb.com>2021-05-12 10:03:06 -0400
committerEvergreen Agent <no-reply@evergreen.mongodb.com>2021-05-12 20:27:42 +0000
commit5641c44b8e7a781a01b85a01f5a5764e3506661a (patch)
tree599afdb9f13c23a6bf262f5104908486c2a8a2c8 /src/mongo/db/repl/oplog.cpp
parent7df553360a1d8137b328ecf7d4a450025b6aeb99 (diff)
downloadmongo-5641c44b8e7a781a01b85a01f5a5764e3506661a.tar.gz
SERVER-56713: Avoid creating retryable find and modify images during initial sync.
Diffstat (limited to 'src/mongo/db/repl/oplog.cpp')
-rw-r--r--src/mongo/db/repl/oplog.cpp63
1 files changed, 37 insertions, 26 deletions
diff --git a/src/mongo/db/repl/oplog.cpp b/src/mongo/db/repl/oplog.cpp
index 232b7a5b4ae..31b8fd82d85 100644
--- a/src/mongo/db/repl/oplog.cpp
+++ b/src/mongo/db/repl/oplog.cpp
@@ -165,24 +165,6 @@ void applyImportCollectionDefault(OperationContext* opCtx,
"isDryRun"_attr = isDryRun);
}
-/**
- * Remove this function when proper lifetime of the config.image_collection is in place.
- */
-void createConfigImagesIfNecessary_temporary(OperationContext* opCtx) {
- AutoGetCollection configImages(
- opCtx, NamespaceString::kConfigImagesNamespace, LockMode::MODE_IX);
- if (configImages.getCollection()) {
- return;
- }
-
- repl::UnreplicatedWritesBlock unreplicated(opCtx);
- CollectionOptions options;
- options.uuid = UUID::gen();
- invariant(DatabaseHolder::get(opCtx)
- ->getDb(opCtx, NamespaceString::kConfigImagesNamespace.db())
- ->createCollection(opCtx, NamespaceString::kConfigImagesNamespace, options));
-}
-
} // namespace
ApplyImportCollectionFn applyImportCollection = applyImportCollectionDefault;
@@ -256,19 +238,28 @@ void createIndexForApplyOps(OperationContext* opCtx,
opCtx->recoveryUnit()->abandonSnapshot();
}
+/**
+ * @param dataImage can be BSONObj::isEmpty to signal the node is in initial sync and must
+ * invalidate relevant image collection data.
+ */
void writeToImageCollection(OperationContext* opCtx,
const LogicalSessionId& sessionId,
+ const TxnNumber txnNum,
const Timestamp timestamp,
repl::RetryImageEnum imageKind,
const BSONObj& dataImage,
bool* upsertConfigImage) {
- createConfigImagesIfNecessary_temporary(opCtx);
AutoGetCollection autoColl(opCtx, NamespaceString::kConfigImagesNamespace, LockMode::MODE_IX);
repl::ImageEntry imageEntry;
imageEntry.set_id(sessionId);
+ imageEntry.setTxnNumber(txnNum);
imageEntry.setTs(timestamp);
imageEntry.setImageKind(imageKind);
imageEntry.setImage(dataImage);
+ if (dataImage.isEmpty()) {
+ imageEntry.setInvalidated(true);
+ imageEntry.setInvalidatedReason("initial sync"_sd);
+ }
UpdateRequest request;
request.setNamespaceString(NamespaceString::kConfigImagesNamespace);
@@ -1437,10 +1428,12 @@ Status applyOperation_inlock(OperationContext* opCtx,
request.setUpdateModification(std::move(updateMod));
request.setUpsert(upsert);
request.setFromOplogApplication(true);
- if (op.getNeedsRetryImage() == repl::RetryImageEnum::kPreImage) {
- request.setReturnDocs(UpdateRequest::ReturnDocOption::RETURN_OLD);
- } else if (op.getNeedsRetryImage() == repl::RetryImageEnum::kPostImage) {
- request.setReturnDocs(UpdateRequest::ReturnDocOption::RETURN_NEW);
+ if (mode != OplogApplication::Mode::kInitialSync) {
+ if (op.getNeedsRetryImage() == repl::RetryImageEnum::kPreImage) {
+ request.setReturnDocs(UpdateRequest::ReturnDocOption::RETURN_OLD);
+ } else if (op.getNeedsRetryImage() == repl::RetryImageEnum::kPostImage) {
+ request.setReturnDocs(UpdateRequest::ReturnDocOption::RETURN_NEW);
+ }
}
Timestamp timestamp;
@@ -1556,8 +1549,12 @@ Status applyOperation_inlock(OperationContext* opCtx,
if (op.getNeedsRetryImage()) {
writeToImageCollection(opCtx,
op.getSessionId().get(),
+ op.getTxnNumber().get(),
op.getTimestamp(),
op.getNeedsRetryImage().get(),
+ // If we did not request an image because we're in
+ // initial sync, the value passed in here is conveniently
+ // the empty BSONObj.
ur.requestedDocImage,
&upsertConfigImage);
}
@@ -1609,17 +1606,31 @@ Status applyOperation_inlock(OperationContext* opCtx,
DeleteRequest request;
request.setNsString(requestNss);
request.setQuery(deleteCriteria);
- if (op.getNeedsRetryImage() == repl::RetryImageEnum::kPreImage) {
+ if (mode != OplogApplication::Mode::kInitialSync &&
+ op.getNeedsRetryImage() == repl::RetryImageEnum::kPreImage) {
+ // When in initial sync, we'll pass an empty image into
+ // `writeToImageCollection`.
request.setReturnDeleted(true);
}
DeleteResult result = deleteObject(opCtx, collection, request);
- if (result.nDeleted == 1 && op.getNeedsRetryImage()) {
+ if (op.getNeedsRetryImage()) {
+ // Even if `result.nDeleted` is 0, we want to perform a write to the
+ // imageCollection to advance the txnNumber/ts and invalidate the image. This
+ // isn't strictly necessary for correctness -- the `config.transactions` table
+ // is responsible for whether to retry. The motivation here is to simply reduce
+ // the number of states related documents in the two collections can be in.
+ BSONObj imageDoc;
+ if (result.nDeleted > 0 && mode != OplogApplication::Mode::kInitialSync) {
+ imageDoc = result.requestedPreImage.get();
+ }
+
writeToImageCollection(opCtx,
op.getSessionId().get(),
+ op.getTxnNumber().get(),
op.getTimestamp(),
repl::RetryImageEnum::kPreImage,
- result.requestedPreImage.get(),
+ imageDoc,
&upsertConfigImage);
}