From 8b9eaa903128dea6c70093bddd8d2a241473ac24 Mon Sep 17 00:00:00 2001 From: Andrew Shuvalov Date: Mon, 24 May 2021 23:12:15 +0000 Subject: SERVER-56375: [RRFaM] BACKPORT-8905 Have delete path write to config.transactions --- src/mongo/db/SConscript | 1 + src/mongo/db/op_observer_impl.cpp | 50 ++++++++++++++++++++++++++------------- src/mongo/db/ops/delete.cpp | 20 ++++++++++++++++ src/mongo/db/ops/delete.h | 11 +++++++++ src/mongo/db/repl/oplog.cpp | 20 ++++++++++++++-- 5 files changed, 83 insertions(+), 19 deletions(-) diff --git a/src/mongo/db/SConscript b/src/mongo/db/SConscript index 0736608db0f..30058745a85 100644 --- a/src/mongo/db/SConscript +++ b/src/mongo/db/SConscript @@ -761,6 +761,7 @@ env.Library( 'session_catalog', ], LIBDEPS_PRIVATE=[ + '$BUILD_DIR/mongo/db/repl/repl_server_parameters', '$BUILD_DIR/mongo/idl/idl_parser', '$BUILD_DIR/mongo/idl/server_parameter', '$BUILD_DIR/mongo/util/concurrency/thread_pool', diff --git a/src/mongo/db/op_observer_impl.cpp b/src/mongo/db/op_observer_impl.cpp index e0df138b418..8d01ddd1583 100644 --- a/src/mongo/db/op_observer_impl.cpp +++ b/src/mongo/db/op_observer_impl.cpp @@ -171,22 +171,6 @@ struct OpTimeBundle { Date_t wallClockTime; }; -void writeToImagesCollection(OperationContext* opCtx, - BSONObj image, - repl::RetryImageEnum imageKind, - Timestamp ts) { - repl::ImageEntry imageEntry; - invariant(opCtx->getLogicalSessionId()); - imageEntry.set_id(*opCtx->getLogicalSessionId()); - imageEntry.setTs(ts); - imageEntry.setImage(std::move(image)); - imageEntry.setImageKind(imageKind); - repl::UnreplicatedWritesBlock unreplicated(opCtx); - AutoGetCollection imageCollectionRaii( - opCtx, NamespaceString::kConfigImagesNamespace, LockMode::MODE_IX); - Helpers::upsert(opCtx, NamespaceString::kConfigImagesNamespace.toString(), imageEntry.toBSON()); -} - /** * Write oplog entry(ies) for the update operation. */ @@ -354,6 +338,25 @@ OpTimeBundle replLogApplyOps(OperationContext* opCtx, return times; } +void writeToImageCollection(OperationContext* opCtx, + const LogicalSessionId& sessionId, + const Timestamp timestamp, + repl::RetryImageEnum imageKind, + const BSONObj& dataImage) { + repl::ImageEntry imageEntry; + invariant(opCtx->getLogicalSessionId()); + imageEntry.set_id(sessionId); + imageEntry.setTxnNumber(opCtx->getTxnNumber().get()); + imageEntry.setTs(timestamp); + imageEntry.setImageKind(imageKind); + imageEntry.setImage(dataImage); + + repl::UnreplicatedWritesBlock unreplicated(opCtx); + AutoGetCollection imageCollectionRaii( + opCtx, NamespaceString::kConfigImagesNamespace, LockMode::MODE_IX); + Helpers::upsert(opCtx, NamespaceString::kConfigImagesNamespace.toString(), imageEntry.toBSON()); +} + } // namespace BSONObj OpObserverImpl::getDocumentKey(OperationContext* opCtx, @@ -621,7 +624,11 @@ void OpObserverImpl::onUpdate(OperationContext* opCtx, const OplogUpdateEntryArg imageDoc = args.updateArgs.updatedDoc; imageKind = repl::RetryImageEnum::kPostImage; } - writeToImagesCollection(opCtx, imageDoc, imageKind, opTime.writeOpTime.getTimestamp()); + writeToImageCollection(opCtx, + *opCtx->getLogicalSessionId(), + opTime.writeOpTime.getTimestamp(), + imageKind, + imageDoc); } SessionTxnRecord sessionTxnRecord; sessionTxnRecord.setLastWriteOpTime(opTime.writeOpTime); @@ -687,6 +694,15 @@ void OpObserverImpl::onDelete(OperationContext* opCtx, args.deletedDoc ? boost::optional(*(args.deletedDoc)) : boost::none; opTime = replLogDelete( opCtx, nss, uuid, stmtId, args.fromMigrate, deletedDoc, storeImagesInSideCollection); + + if (storeImagesInSideCollection && deletedDoc && opCtx->getTxnNumber()) { + writeToImageCollection(opCtx, + *opCtx->getLogicalSessionId(), + opTime.writeOpTime.getTimestamp(), + repl::RetryImageEnum::kPreImage, + *deletedDoc); + } + SessionTxnRecord sessionTxnRecord; sessionTxnRecord.setLastWriteOpTime(opTime.writeOpTime); sessionTxnRecord.setLastWriteDate(opTime.wallClockTime); diff --git a/src/mongo/db/ops/delete.cpp b/src/mongo/db/ops/delete.cpp index 3a95b360a47..78ee9f8d924 100644 --- a/src/mongo/db/ops/delete.cpp +++ b/src/mongo/db/ops/delete.cpp @@ -64,4 +64,24 @@ long long deleteObjects(OperationContext* opCtx, return DeleteStage::getNumDeleted(*exec); } +DeleteResult deleteObject(OperationContext* opCtx, + Collection* collection, + const DeleteRequest& request) { + ParsedDelete parsedDelete(opCtx, &request); + uassertStatusOK(parsedDelete.parseRequest()); + + // This method doesn't support multi-deletes. + invariant(!request.isMulti()); + + auto exec = uassertStatusOK( + getExecutorDelete(opCtx, &CurOp::get(opCtx)->debug(), collection, &parsedDelete)); + + BSONObj docImage; + if (exec->getNext(&docImage, nullptr) == PlanExecutor::IS_EOF) { + return {}; + } + + return {1, request.shouldReturnDeleted() ? docImage.getOwned() : BSONObj()}; +} + } // namespace mongo diff --git a/src/mongo/db/ops/delete.h b/src/mongo/db/ops/delete.h index b26f583d460..c73c353ff86 100644 --- a/src/mongo/db/ops/delete.h +++ b/src/mongo/db/ops/delete.h @@ -30,6 +30,7 @@ #pragma once #include "mongo/db/jsobj.h" +#include "mongo/db/ops/delete_request.h" #include "mongo/db/query/plan_executor.h" @@ -50,4 +51,14 @@ long long deleteObjects(OperationContext* opCtx, bool justOne, bool god = false, bool fromMigrate = false); + +struct DeleteResult { + long long nDeleted; + boost::optional requestedPreImage; +}; + +DeleteResult deleteObject(OperationContext* opCtx, + Collection* collection, + const DeleteRequest& request); + } // namespace mongo diff --git a/src/mongo/db/repl/oplog.cpp b/src/mongo/db/repl/oplog.cpp index 8e842732f86..cebb59e3990 100644 --- a/src/mongo/db/repl/oplog.cpp +++ b/src/mongo/db/repl/oplog.cpp @@ -68,6 +68,7 @@ #include "mongo/db/namespace_string.h" #include "mongo/db/op_observer.h" #include "mongo/db/ops/delete.h" +#include "mongo/db/ops/delete_request.h" #include "mongo/db/ops/update.h" #include "mongo/db/repl/apply_ops.h" #include "mongo/db/repl/bgsync.h" @@ -1791,6 +1792,7 @@ Status applyOperation_inlock(OperationContext* opCtx, } const StringData ns = fieldNs.valueStringDataSafe(); + bool upsertConfigImage = true; writeConflictRetry(opCtx, "applyOps_delete", ns, [&] { WriteUnitOfWork wuow(opCtx); if (timestamp != Timestamp::min()) { @@ -1798,8 +1800,22 @@ Status applyOperation_inlock(OperationContext* opCtx, } if (opType[1] == 0) { - const auto justOne = true; - deleteObjects(opCtx, collection, requestNss, deleteCriteria, justOne); + const bool kNeedsRetryImage = + op.hasField(OplogEntryBase::kNeedsRetryImageFieldName); + DeleteRequest request(requestNss); + request.setQuery(deleteCriteria); + if (kNeedsRetryImage) { + request.setReturnDeleted(true); + } + + DeleteResult result = deleteObject(opCtx, collection, request); + if (result.nDeleted == 1 && kNeedsRetryImage) { + writeToImageCollection(opCtx, + op, + result.requestedPreImage.get(), + repl::RetryImageEnum::kPreImage, + &upsertConfigImage); + } } else verify(opType[1] == 'b'); // "db" advertisement wuow.commit(); -- cgit v1.2.1