summaryrefslogtreecommitdiff
path: root/src/mongo/db/read_concern_mongod.cpp
diff options
context:
space:
mode:
authorLouis Williams <louis.williams@mongodb.com>2019-06-11 13:23:46 -0400
committerLouis Williams <louis.williams@mongodb.com>2019-06-11 13:23:46 -0400
commitc23da6ac95bf5f687b6d21f2cc86f4775be88cd5 (patch)
tree01ddfa412a5cddf83a46eae66d387370fe4053b6 /src/mongo/db/read_concern_mongod.cpp
parent01e68d5ac26a64b5b2d3a836428c07e3874488bf (diff)
downloadmongo-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.cpp34
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",