diff options
Diffstat (limited to 'src/mongo/db/repl/oplog.cpp')
-rw-r--r-- | src/mongo/db/repl/oplog.cpp | 28 |
1 files changed, 19 insertions, 9 deletions
diff --git a/src/mongo/db/repl/oplog.cpp b/src/mongo/db/repl/oplog.cpp index 50d7d62825d..499312b3b14 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_participant.h" #include "mongo/platform/random.h" #include "mongo/scripting/engine.h" #include "mongo/stdx/memory.h" @@ -998,7 +999,14 @@ std::map<std::string, ApplyOpMetadata> opsMap = { const BSONElement& ui, BSONObj& cmd, const OpTime& opTime, - OplogApplication::Mode mode) -> Status { return Status::OK(); }}}, + OplogApplication::Mode mode) -> Status { + // Session has been checked out by sync_tail. + auto transaction = TransactionParticipant::get(opCtx); + invariant(transaction); + transaction->unstashTransactionResources(opCtx, "abortTransaction"); + transaction->abortActiveTransaction(opCtx); + return Status::OK(); + }}}, }; } // namespace @@ -1529,6 +1537,9 @@ Status applyCommand_inlock(OperationContext* opCtx, return {ErrorCodes::InvalidNamespace, "invalid ns: " + std::string(nss.ns())}; } { + // Command application doesn't always acquire the global writer lock for transaction + // commands, so we acquire its own locks here. + Lock::DBLock lock(opCtx, nss.db(), MODE_IS); Database* db = DatabaseHolder::getDatabaseHolder().get(opCtx, nss.ns()); if (db && !db->getCollection(opCtx, nss) && db->getViewCatalog()->lookup(opCtx, nss.ns())) { return {ErrorCodes::CommandNotSupportedOnView, @@ -1553,10 +1564,6 @@ Status applyCommand_inlock(OperationContext* opCtx, << redact(op)); } - // Applying commands in repl is done under Global W-lock, so it is safe to not - // perform the current DB checks after reacquiring the lock. - invariant(opCtx->lockState()->isW()); - // Parse optime from oplog entry unless we are applying this command in standalone or on a // primary (replicated writes enabled). OpTime opTime; @@ -1567,7 +1574,7 @@ Status applyCommand_inlock(OperationContext* opCtx, } } - const bool assignCommandTimestamp = [opCtx, mode, &op] { + const bool assignCommandTimestamp = [opCtx, mode, &op, &o] { const auto replMode = ReplicationCoordinator::get(opCtx)->getReplicationMode(); if (opCtx->writesAreReplicated()) { // We do not assign timestamps on replicated writes since they will get their oplog @@ -1575,6 +1582,11 @@ Status applyCommand_inlock(OperationContext* opCtx, return false; } + // Don't assign commit timestamp for transaction commands. + const StringData commandName(o.firstElementFieldName()); + if (op.getBoolField("prepare") || commandName == "abortTransaction") + return false; + switch (replMode) { case ReplicationCoordinator::modeReplSet: { // The 'applyOps' command never logs 'applyOps' oplog entries with nested @@ -1582,9 +1594,7 @@ Status applyCommand_inlock(OperationContext* opCtx, // command on secondaries. Thus, the timestamps in the command oplog // entries are always real timestamps from this oplog and we should // timestamp our writes with them. - // - // However, if "prepare" is specified, don't assign commit timestamp. - return !op.getBoolField("prepare"); + return true; } case ReplicationCoordinator::modeNone: { // Only assign timestamps on standalones during replication recovery when |