diff options
Diffstat (limited to 'src/mongo/db/commands/find_cmd.cpp')
-rw-r--r-- | src/mongo/db/commands/find_cmd.cpp | 34 |
1 files changed, 34 insertions, 0 deletions
diff --git a/src/mongo/db/commands/find_cmd.cpp b/src/mongo/db/commands/find_cmd.cpp index 4120b38cd6d..39dee1b5f29 100644 --- a/src/mongo/db/commands/find_cmd.cpp +++ b/src/mongo/db/commands/find_cmd.cpp @@ -59,10 +59,13 @@ #include "mongo/db/transaction_participant.h" #include "mongo/logv2/log.h" #include "mongo/rpc/get_status_from_command_result.h" +#include "mongo/util/fail_point.h" namespace mongo { namespace { +MONGO_FAIL_POINT_DEFINE(allowExternalReadsForReverseOplogScanRule); + const auto kTermField = "term"_sd; // Older client code before FCV 5.1 could still send 'ntoreturn' to mean a 'limit' or 'batchSize'. @@ -424,6 +427,37 @@ public: opCtx->lockState()->skipAcquireTicket(); } + // If this read represents a reverse oplog scan, we want to bypass oplog visibility + // rules in the case of secondaries. We normally only read from these nodes at batch + // boundaries, but in this specific case we should fetch all new entries, to be + // consistent with any catalog changes that might be observable before the batch is + // finalized. This special rule for reverse oplog scans is needed by replication + // initial sync, for the purposes of calculating the stopTimestamp correctly. + boost::optional<PinReadSourceBlock> pinReadSourceBlock; + if (isOplogNss) { + auto reverseScan = false; + + auto cmdSort = findCommand->getSort(); + if (!cmdSort.isEmpty()) { + BSONElement natural = cmdSort[query_request_helper::kNaturalSortField]; + if (natural) { + reverseScan = natural.safeNumberInt() < 0; + } + } + + auto isInternal = (opCtx->getClient()->session() && + (opCtx->getClient()->session()->getTags() & + transport::Session::kInternalClient)); + + if (MONGO_unlikely(allowExternalReadsForReverseOplogScanRule.shouldFail())) { + isInternal = true; + } + + if (reverseScan && isInternal) { + pinReadSourceBlock.emplace(opCtx->recoveryUnit()); + } + } + // Acquire locks. If the query is on a view, we release our locks and convert the query // request into an aggregation command. boost::optional<AutoGetCollectionForReadCommandMaybeLockFree> ctx; |