From eace76975fd1c521993e82fdc0c2c7833f84ed48 Mon Sep 17 00:00:00 2001 From: Jonathan Reams Date: Wed, 16 Jan 2019 11:38:30 -0500 Subject: SERVER-38071 Abandon snapshot after findOne() in AuthzManagerExternalState --- src/mongo/db/auth/authz_manager_external_state_d.cpp | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/src/mongo/db/auth/authz_manager_external_state_d.cpp b/src/mongo/db/auth/authz_manager_external_state_d.cpp index ed9a4053f5e..cf3d21493c8 100644 --- a/src/mongo/db/auth/authz_manager_external_state_d.cpp +++ b/src/mongo/db/auth/authz_manager_external_state_d.cpp @@ -62,6 +62,9 @@ AuthzManagerExternalStateMongod::makeAuthzSessionExternalState(AuthorizationMana class AuthzLock : public AuthzManagerExternalState::StateLock { public: + // TODO When SERVER-39289 is done, we should fassert if we are in an active storage engine + // transaction when the AuthzLock is first acquired. We do not want to mix authz database + // operations with user database operations. explicit AuthzLock(OperationContext* opCtx) : _lock(opCtx, AuthorizationManager::usersCollectionNamespace.db(), @@ -115,6 +118,18 @@ Status AuthzManagerExternalStateMongod::findOne(OperationContext* opCtx, *result = found.getOwned(); return Status::OK(); } + + // Calling findOne starts a storage engine transaction/snapshot if one hasn't been started + // already. Since we are not holding a lock on the authz collections between calls to + // findOne(), the minimum valid timestamp may change between calls and trying to re-use the + // old snapshot may cause an invariant in the storage engine. + // + // See SERVER-38071 + const auto recoveryUnit = opCtx->recoveryUnit(); + if (recoveryUnit) { + recoveryUnit->abandonSnapshot(); + } + return Status(ErrorCodes::NoMatchingDocument, mongoutils::str::stream() << "No document in " << collectionName.ns() << " matches " -- cgit v1.2.1