From 6b3e341703b781bb1ff7b1263406a0f1d28dd77c Mon Sep 17 00:00:00 2001 From: Gregory Noma Date: Tue, 25 Aug 2020 16:07:00 -0400 Subject: SERVER-50365 Use short WT transaction rollback timeout in the multi-document transaction expirer thread --- ...iodic_runner_job_abort_expired_transactions.cpp | 5 +++++ src/mongo/db/storage/recovery_unit.h | 10 +++++++++ .../wiredtiger/wiredtiger_recovery_unit.cpp | 25 +++++++++++++--------- src/mongo/db/transaction_participant.cpp | 7 ++++++ src/mongo/db/transaction_participant.h | 2 ++ 5 files changed, 39 insertions(+), 10 deletions(-) (limited to 'src/mongo') diff --git a/src/mongo/db/periodic_runner_job_abort_expired_transactions.cpp b/src/mongo/db/periodic_runner_job_abort_expired_transactions.cpp index 4ab8aed0dec..8038e7bbcb5 100644 --- a/src/mongo/db/periodic_runner_job_abort_expired_transactions.cpp +++ b/src/mongo/db/periodic_runner_job_abort_expired_transactions.cpp @@ -102,6 +102,11 @@ void PeriodicThreadToAbortExpiredTransactions::_init(ServiceContext* serviceCont // non-transaction, exclusive lock taking operation blocked // behind an active transaction's intent lock. opCtx->lockState()->setMaxLockTimeout(Milliseconds(0)); + + // This thread needs storage rollback to complete timely, so instruct the storage + // engine to not do any extra eviction for this thread, if supported. + opCtx->recoveryUnit()->setNoEvictionAfterRollback(); + try { killAllExpiredTransactions(opCtx.get()); } catch (ExceptionForCat& ex) { diff --git a/src/mongo/db/storage/recovery_unit.h b/src/mongo/db/storage/recovery_unit.h index 6242a69d777..5c8be96b528 100644 --- a/src/mongo/db/storage/recovery_unit.h +++ b/src/mongo/db/storage/recovery_unit.h @@ -633,6 +633,14 @@ public: _mustBeTimestamped = true; } + void setNoEvictionAfterRollback() { + _noEvictionAfterRollback = true; + } + + bool getNoEvictionAfterRollback() const { + return _noEvictionAfterRollback; + } + protected: RecoveryUnit(); @@ -673,6 +681,8 @@ protected: bool _mustBeTimestamped = false; + bool _noEvictionAfterRollback = false; + private: // Sets the snapshot associated with this RecoveryUnit to a new globally unique id number. void assignNextSnapshotId(); diff --git a/src/mongo/db/storage/wiredtiger/wiredtiger_recovery_unit.cpp b/src/mongo/db/storage/wiredtiger/wiredtiger_recovery_unit.cpp index 8eba439563c..1167fd673f3 100644 --- a/src/mongo/db/storage/wiredtiger/wiredtiger_recovery_unit.cpp +++ b/src/mongo/db/storage/wiredtiger/wiredtiger_recovery_unit.cpp @@ -374,17 +374,22 @@ void WiredTigerRecoveryUnit::_txnClose(bool commit) { } wtRet = s->commit_transaction(s, conf.str().c_str()); - LOGV2_DEBUG(22412, - 3, - "WT commit_transaction for snapshot id {snapshotId}", - "snapshotId"_attr = getSnapshotId().toNumber()); + + LOGV2_DEBUG( + 22412, 3, "WT commit_transaction", "snapshotId"_attr = getSnapshotId().toNumber()); } else { - wtRet = s->rollback_transaction(s, nullptr); - invariant(!wtRet); - LOGV2_DEBUG(22413, - 3, - "WT rollback_transaction for snapshot id {snapshotId}", - "snapshotId"_attr = getSnapshotId().toNumber()); + StringBuilder config; + if (_noEvictionAfterRollback) { + // The only point at which rollback_transaction() can time out is in the bonus-eviction + // phase. If the timeout expires here, the function will stop the eviction and return + // success. It cannot return an error due to timeout. + config << "operation_timeout_ms=1,"; + } + + wtRet = s->rollback_transaction(s, config.str().c_str()); + + LOGV2_DEBUG( + 22413, 3, "WT rollback_transaction", "snapshotId"_attr = getSnapshotId().toNumber()); } if (_isTimestamped) { diff --git a/src/mongo/db/transaction_participant.cpp b/src/mongo/db/transaction_participant.cpp index f4e650b47f3..d3772edb7db 100644 --- a/src/mongo/db/transaction_participant.cpp +++ b/src/mongo/db/transaction_participant.cpp @@ -830,6 +830,10 @@ void TransactionParticipant::TxnResources::release(OperationContext* opCtx) { readConcernArgs = _readConcernArgs; } +void TransactionParticipant::TxnResources::setNoEvictionAfterRollback() { + _recoveryUnit->setNoEvictionAfterRollback(); +} + TransactionParticipant::SideTransactionBlock::SideTransactionBlock(OperationContext* opCtx) : _opCtx(opCtx) { // Do nothing if we are already in a SideTransactionBlock. We can tell we are already in a @@ -1662,6 +1666,9 @@ void TransactionParticipant::Participant::_abortTransactionOnSession(OperationCo : TransactionState::kAbortedWithoutPrepare; stdx::lock_guard lk(*opCtx->getClient()); + if (o().txnResourceStash && opCtx->recoveryUnit()->getNoEvictionAfterRollback()) { + o(lk).txnResourceStash->setNoEvictionAfterRollback(); + } _resetTransactionState(lk, nextState); } diff --git a/src/mongo/db/transaction_participant.h b/src/mongo/db/transaction_participant.h index 8fad2122368..1c3164a51fc 100644 --- a/src/mongo/db/transaction_participant.h +++ b/src/mongo/db/transaction_participant.h @@ -221,6 +221,8 @@ public: return _readConcernArgs; } + void setNoEvictionAfterRollback(); + private: bool _released = false; std::unique_ptr _locker; -- cgit v1.2.1