summaryrefslogtreecommitdiff
path: root/src/mongo/db/db_raii.cpp
diff options
context:
space:
mode:
authorWilliam Schultz <william.schultz@mongodb.com>2019-04-23 14:28:50 -0400
committerWilliam Schultz <william.schultz@mongodb.com>2019-04-23 14:28:50 -0400
commit75aac812bfce0419d68c65d48233f94c06aaeafd (patch)
tree6cc5220614e4374f04a1fab8fdbf5667e73f3a7e /src/mongo/db/db_raii.cpp
parent8d8f1d7b95a7d8afd5bf1d2536b861e467e7ca81 (diff)
downloadmongo-75aac812bfce0419d68c65d48233f94c06aaeafd.tar.gz
SERVER-40706 AutoGetCollectionForRead invariant should permit kNoOverlap read source when there are conflicting catalog changes
Diffstat (limited to 'src/mongo/db/db_raii.cpp')
-rw-r--r--src/mongo/db/db_raii.cpp20
1 files changed, 19 insertions, 1 deletions
diff --git a/src/mongo/db/db_raii.cpp b/src/mongo/db/db_raii.cpp
index d4d876e4214..3d111f8a195 100644
--- a/src/mongo/db/db_raii.cpp
+++ b/src/mongo/db/db_raii.cpp
@@ -162,7 +162,10 @@ AutoGetCollectionForRead::AutoGetCollectionForRead(OperationContext* opCtx,
}
invariant(lastAppliedTimestamp ||
- readSource == RecoveryUnit::ReadSource::kMajorityCommitted);
+ // The kMajorityCommitted and kNoOverlap read sources already read from timestamps
+ // that are safe with respect to concurrent secondary batch application.
+ readSource == RecoveryUnit::ReadSource::kMajorityCommitted ||
+ readSource == RecoveryUnit::ReadSource::kNoOverlap);
invariant(readConcernLevel != repl::ReadConcernLevel::kSnapshotReadConcern);
// Yield locks in order to do the blocking call below.
@@ -192,6 +195,21 @@ AutoGetCollectionForRead::AutoGetCollectionForRead(OperationContext* opCtx,
opCtx->recoveryUnit()->setTimestampReadSource(RecoveryUnit::ReadSource::kUnset);
}
+ // If there are pending catalog changes when using a no-overlap read source, we choose to
+ // take the PBWM lock to conflict with any in-progress batches. This prevents us from idly
+ // spinning in this loop trying to get a new read timestamp ahead of the minimum visible
+ // snapshot. This helps us guarantee liveness (i.e. we can eventually get a suitable read
+ // timestamp) but should not be necessary for correctness.
+ if (readSource == RecoveryUnit::ReadSource::kNoOverlap) {
+ invariant(!lastAppliedTimestamp); // no-overlap read source selects its own timestamp.
+ _shouldNotConflictWithSecondaryBatchApplicationBlock = boost::none;
+ invariant(opCtx->lockState()->shouldConflictWithSecondaryBatchApplication());
+
+ // Abandon our snapshot but don't change our read source, so that we can select a new
+ // read timestamp on the next loop iteration.
+ opCtx->recoveryUnit()->abandonSnapshot();
+ }
+
if (readSource == RecoveryUnit::ReadSource::kMajorityCommitted) {
replCoord->waitUntilSnapshotCommitted(opCtx, *minSnapshot);
uassertStatusOK(opCtx->recoveryUnit()->obtainMajorityCommittedSnapshot());