diff options
| author | Jordi Serra Torrens <jordi.serra-torrens@mongodb.com> | 2023-06-27 15:42:13 +0000 |
|---|---|---|
| committer | Evergreen Agent <no-reply@evergreen.mongodb.com> | 2023-06-29 13:37:52 +0000 |
| commit | 3d84c0dd4e5d99be0d69003652313e7eaf4cdd74 (patch) | |
| tree | 8d2328c1a0b9b3009db3b41d51c1400ad33d19ca /src/mongo/db/query/plan_executor_impl.cpp | |
| parent | 2ffc5b8e89ed4a7af49bbd1ed9aec502c8f0eae0 (diff) | |
SERVER-61127 Retry multi-writes that hit StaleConfig due to critical section on the shardr6.0.8-rc0r6.0.8
(cherry picked from commit 824b9b7e608687ba0db7af2d5ccc5b6811a46720)
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 c3ae2946a38..55253f6e02d 100644 --- a/src/mongo/db/query/plan_executor_impl.cpp +++ b/src/mongo/db/query/plan_executor_impl.cpp @@ -62,6 +62,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" @@ -360,8 +361,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; |
