diff options
author | Jordi Serra Torrens <jordi.serra-torrens@mongodb.com> | 2022-06-09 07:21:14 +0000 |
---|---|---|
committer | Evergreen Agent <no-reply@evergreen.mongodb.com> | 2022-06-09 08:20:01 +0000 |
commit | 824b9b7e608687ba0db7af2d5ccc5b6811a46720 (patch) | |
tree | 024f48d5525e7f49d6d256282bc0c6647e2fbf94 /src/mongo/db/query/plan_executor_impl.cpp | |
parent | 0c2e70f14d87b17d43fd3af322b604af7e8ea5a6 (diff) | |
download | mongo-824b9b7e608687ba0db7af2d5ccc5b6811a46720.tar.gz |
SERVER-61127 Retry multi-writes that hit StaleConfig due to critical section on the shard
Diffstat (limited to 'src/mongo/db/query/plan_executor_impl.cpp')
-rw-r--r-- | src/mongo/db/query/plan_executor_impl.cpp | 20 |
1 files changed, 19 insertions, 1 deletions
diff --git a/src/mongo/db/query/plan_executor_impl.cpp b/src/mongo/db/query/plan_executor_impl.cpp index 76559f3d003..808b0800d23 100644 --- a/src/mongo/db/query/plan_executor_impl.cpp +++ b/src/mongo/db/query/plan_executor_impl.cpp @@ -60,6 +60,7 @@ #include "mongo/db/query/plan_yield_policy_impl.h" #include "mongo/db/query/yield_policy_callbacks_impl.h" #include "mongo/db/repl/replication_coordinator.h" +#include "mongo/db/s/operation_sharding_state.h" #include "mongo/db/service_context.h" #include "mongo/logv2/log.h" #include "mongo/util/fail_point.h" @@ -361,8 +362,25 @@ PlanExecutor::ExecState PlanExecutorImpl::_getNextImpl(Snapshotted<Document>* ob // 2) some stage requested a yield, or // 3) we need to yield and retry due to a WriteConflictException. // In all cases, the actual yielding happens here. + + const auto whileYieldingFn = [&]() { + // If we yielded because we encountered a sharding critical section, wait for the + // critical section to end before continuing. By waiting for the critical section to be + // exited we avoid busy spinning immediately and encountering the same critical section + // again. It is important that this wait happens after having released the lock + // hierarchy -- otherwise deadlocks could happen, or the very least, locks would be + // unnecessarily held while waiting. + const auto& shardingCriticalSection = planExecutorShardingCriticalSectionFuture(_opCtx); + if (shardingCriticalSection) { + OperationShardingState::waitForCriticalSectionToComplete(_opCtx, + *shardingCriticalSection) + .ignore(); + planExecutorShardingCriticalSectionFuture(_opCtx).reset(); + } + }; + if (_yieldPolicy->shouldYieldOrInterrupt(_opCtx)) { - uassertStatusOK(_yieldPolicy->yieldOrInterrupt(_opCtx)); + uassertStatusOK(_yieldPolicy->yieldOrInterrupt(_opCtx, whileYieldingFn)); } WorkingSetID id = WorkingSet::INVALID_ID; |