diff options
author | Vesselina Ratcheva <vesselina.ratcheva@10gen.com> | 2019-05-24 17:22:30 -0400 |
---|---|---|
committer | Vesselina Ratcheva <vesselina.ratcheva@10gen.com> | 2019-05-29 13:05:21 -0400 |
commit | cb45824b458c1b3714a379c5c658e1e89238c03d (patch) | |
tree | c4e080a13ee892672dd6dc33476be9aad89532cc /src/mongo/db/transaction_participant.cpp | |
parent | e11c234484fe58681597ba74fd23fa76de734250 (diff) | |
download | mongo-cb45824b458c1b3714a379c5c658e1e89238c03d.tar.gz |
SERVER-41317 Push commit transaction's check for a majority-committed prepare down into the TransactionParticipant
Diffstat (limited to 'src/mongo/db/transaction_participant.cpp')
-rw-r--r-- | src/mongo/db/transaction_participant.cpp | 19 |
1 files changed, 17 insertions, 2 deletions
diff --git a/src/mongo/db/transaction_participant.cpp b/src/mongo/db/transaction_participant.cpp index 3b963c9d7b8..0ccc127e94d 100644 --- a/src/mongo/db/transaction_participant.cpp +++ b/src/mongo/db/transaction_participant.cpp @@ -81,6 +81,8 @@ MONGO_FAIL_POINT_DEFINE(hangAfterSettingPrepareStartTime); MONGO_FAIL_POINT_DEFINE(hangBeforeReleasingTransactionOplogHole); +MONGO_FAIL_POINT_DEFINE(skipCommitTxnCheckPrepareMajorityCommitted); + const auto getTransactionParticipant = Session::declareDecoration<TransactionParticipant>(); // The command names that are allowed in a prepared transaction. @@ -1260,8 +1262,10 @@ void TransactionParticipant::Participant::commitPreparedTransaction( // transaction was prepared, we dropped the RSTL. We do not need to reacquire the PBWM because // if we're not the primary we will uassert anyways. repl::ReplicationStateTransitionLockGuard rstl(opCtx, MODE_IX); + + const auto replCoord = repl::ReplicationCoordinator::get(opCtx); + if (opCtx->writesAreReplicated()) { - auto replCoord = repl::ReplicationCoordinator::get(opCtx); uassert(ErrorCodes::NotMaster, "Not primary so we cannot commit a prepared transaction", replCoord->canAcceptWritesForDatabase(opCtx, "admin")); @@ -1272,9 +1276,20 @@ void TransactionParticipant::Participant::commitPreparedTransaction( o().txnState.isPrepared()); uassert( ErrorCodes::InvalidOptions, "'commitTimestamp' cannot be null", !commitTimestamp.isNull()); + + const auto prepareTimestamp = o().prepareOpTime.getTimestamp(); + uassert(ErrorCodes::InvalidOptions, "'commitTimestamp' must be greater than or equal to 'prepareTimestamp'", - commitTimestamp >= o().prepareOpTime.getTimestamp()); + commitTimestamp >= prepareTimestamp); + + if (!commitOplogEntryOpTime) { + uassert(ErrorCodes::InvalidOptions, + "commitTransaction for a prepared transaction cannot be run before its prepare " + "oplog entry has been majority committed", + replCoord->getLastCommittedOpTime().getTimestamp() >= prepareTimestamp || + MONGO_FAIL_POINT(skipCommitTxnCheckPrepareMajorityCommitted)); + } { stdx::lock_guard<Client> lk(*opCtx->getClient()); |