diff options
author | Louis Williams <louis.williams@mongodb.com> | 2019-06-11 13:23:46 -0400 |
---|---|---|
committer | Louis Williams <louis.williams@mongodb.com> | 2019-06-11 13:23:46 -0400 |
commit | c23da6ac95bf5f687b6d21f2cc86f4775be88cd5 (patch) | |
tree | 01ddfa412a5cddf83a46eae66d387370fe4053b6 /src/mongo/db/read_concern_mongod.cpp | |
parent | 01e68d5ac26a64b5b2d3a836428c07e3874488bf (diff) | |
download | mongo-c23da6ac95bf5f687b6d21f2cc86f4775be88cd5.tar.gz |
SERVER-41525 Use ignore_prepare=force for transactions that correctly do writes while ignoring prepare conflicts
Diffstat (limited to 'src/mongo/db/read_concern_mongod.cpp')
-rw-r--r-- | src/mongo/db/read_concern_mongod.cpp | 34 |
1 files changed, 24 insertions, 10 deletions
diff --git a/src/mongo/db/read_concern_mongod.cpp b/src/mongo/db/read_concern_mongod.cpp index e362702fb2e..7844f28ebea 100644 --- a/src/mongo/db/read_concern_mongod.cpp +++ b/src/mongo/db/read_concern_mongod.cpp @@ -43,6 +43,7 @@ #include "mongo/db/repl/speculative_majority_read_info.h" #include "mongo/db/s/sharding_state.h" #include "mongo/db/server_options.h" +#include "mongo/db/storage/recovery_unit.h" #include "mongo/s/grid.h" #include "mongo/util/concurrency/notification.h" #include "mongo/util/log.h" @@ -205,25 +206,27 @@ Status makeNoopWriteIfNeeded(OperationContext* opCtx, LogicalTime clusterTime) { } /** - * Returns whether the command should ignore prepare conflicts or not. + * Returns the PrepareConflictBehavior that a command should use given the requested behavior and + * readConcern options. */ -bool shouldIgnorePrepared(PrepareConflictBehavior prepareConflictBehavior, - repl::ReadConcernLevel readConcernLevel, - boost::optional<LogicalTime> afterClusterTime, - boost::optional<LogicalTime> atClusterTime) { +PrepareConflictBehavior getPrepareBehaviorForReadConcern( + PrepareConflictBehavior requestedBehavior, + repl::ReadConcernLevel readConcernLevel, + boost::optional<LogicalTime> afterClusterTime, + boost::optional<LogicalTime> atClusterTime) { // Only these read concern levels are eligible for ignoring prepare conflicts. if (readConcernLevel != repl::ReadConcernLevel::kLocalReadConcern && readConcernLevel != repl::ReadConcernLevel::kAvailableReadConcern && readConcernLevel != repl::ReadConcernLevel::kMajorityReadConcern) { - return false; + return PrepareConflictBehavior::kEnforce; } if (afterClusterTime || atClusterTime) { - return false; + return PrepareConflictBehavior::kEnforce; } - return prepareConflictBehavior == PrepareConflictBehavior::kIgnore; + return requestedBehavior; } } // namespace @@ -367,8 +370,9 @@ MONGO_REGISTER_SHIM(waitForReadConcern) // DBDirectClient should inherit whether or not to ignore prepare conflicts from its parent. if (!opCtx->getClient()->isInDirectClient()) { // Set whether this command should ignore prepare conflicts or not. - opCtx->recoveryUnit()->setIgnorePrepared(shouldIgnorePrepared( - prepareConflictBehavior, readConcernArgs.getLevel(), afterClusterTime, atClusterTime)); + const auto behavior = getPrepareBehaviorForReadConcern( + prepareConflictBehavior, readConcernArgs.getLevel(), afterClusterTime, atClusterTime); + opCtx->recoveryUnit()->setPrepareConflictBehavior(behavior); } return Status::OK(); @@ -394,6 +398,16 @@ MONGO_REGISTER_SHIM(waitForLinearizableReadConcern) "No longer primary when waiting for linearizable read concern"}; } + // With linearizable readConcern, read commands may write to the oplog, which is an + // exception to the rule that writes are not allowed while ignoring prepare conflicts. If we + // are ignoring prepare conflicts (during a read command), force the prepare conflict + // behavior to permit writes. + auto originalBehavior = opCtx->recoveryUnit()->getPrepareConflictBehavior(); + if (originalBehavior == PrepareConflictBehavior::kIgnoreConflicts) { + opCtx->recoveryUnit()->setPrepareConflictBehavior( + PrepareConflictBehavior::kIgnoreConflictsAllowWrites); + } + writeConflictRetry( opCtx, "waitForLinearizableReadConcern", |