diff options
Diffstat (limited to 'src/mongo/db/repl/oplog.cpp')
-rw-r--r-- | src/mongo/db/repl/oplog.cpp | 30 |
1 files changed, 29 insertions, 1 deletions
diff --git a/src/mongo/db/repl/oplog.cpp b/src/mongo/db/repl/oplog.cpp index 43ea709440a..bd41e12bd1e 100644 --- a/src/mongo/db/repl/oplog.cpp +++ b/src/mongo/db/repl/oplog.cpp @@ -86,6 +86,7 @@ #include "mongo/db/stats/counters.h" #include "mongo/db/storage/storage_engine.h" #include "mongo/db/storage/storage_options.h" +#include "mongo/db/transaction_history_iterator.h" #include "mongo/db/transaction_participant.h" #include "mongo/platform/random.h" #include "mongo/scripting/engine.h" @@ -1010,7 +1011,34 @@ std::map<std::string, ApplyOpMetadata> opsMap = { BSONObj& cmd, const OpTime& opTime, const OplogEntry& entry, - OplogApplication::Mode mode) -> Status { return Status::OK(); }}}, + OplogApplication::Mode mode) -> Status { + if (mode == OplogApplication::Mode::kRecovering) { + const auto replCoord = ReplicationCoordinator::get(opCtx); + const auto recoveryTimestamp = replCoord->getRecoveryTimestamp(); + invariant(recoveryTimestamp); + + // If the commitTimestamp is before the recoveryTimestamp, then the data already + // reflects the operations from the transaction. + const auto commitTimestamp = cmd["commitTimestamp"].timestamp(); + if (recoveryTimestamp.get() > commitTimestamp) { + return Status::OK(); + } + + // Get the corresponding prepareTransaction oplog entry. + TransactionHistoryIterator iter(opTime); + invariant(iter.hasNext()); + const auto commitOplogEntry = iter.next(opCtx); + invariant(iter.hasNext()); + const auto prepareOplogEntry = iter.next(opCtx); + + // Transform prepare command into a normal applyOps command. + const auto prepareCmd = prepareOplogEntry.getOperationToApply().removeField("prepare"); + + BSONObjBuilder resultWeDontCareAbout; + return applyOps(opCtx, nsToDatabase(ns), prepareCmd, mode, &resultWeDontCareAbout); + } + return Status::OK(); + }}}, {"abortTransaction", {[](OperationContext* opCtx, const char* ns, |