diff options
author | William Schultz <william.schultz@mongodb.com> | 2019-04-23 14:28:50 -0400 |
---|---|---|
committer | William Schultz <william.schultz@mongodb.com> | 2019-04-23 14:28:50 -0400 |
commit | 75aac812bfce0419d68c65d48233f94c06aaeafd (patch) | |
tree | 6cc5220614e4374f04a1fab8fdbf5667e73f3a7e /src/mongo/db/db_raii.cpp | |
parent | 8d8f1d7b95a7d8afd5bf1d2536b861e467e7ca81 (diff) | |
download | mongo-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.cpp | 20 |
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()); |