summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorSamy Lanka <samy.lanka@mongodb.com>2018-09-28 10:37:14 -0400
committerSamy Lanka <samy.lanka@mongodb.com>2018-10-01 16:27:56 -0400
commitf7b229af67e5d2e8f77009563347c0220988e6b2 (patch)
treea2d1f1ae5022312c798714e730a54faeb45119cb /src
parent3c2eb809fb7f6924612c1900e57cc456bcbb4983 (diff)
downloadmongo-f7b229af67e5d2e8f77009563347c0220988e6b2.tar.gz
SERVER-37030 Make internal reads ignore prepare conflicts by default
Diffstat (limited to 'src')
-rw-r--r--src/mongo/db/read_concern.cpp12
-rw-r--r--src/mongo/db/storage/wiredtiger/wiredtiger_begin_transaction_block.h4
-rw-r--r--src/mongo/db/storage/wiredtiger/wiredtiger_recovery_unit.h6
-rw-r--r--src/mongo/db/storage/wiredtiger/wiredtiger_recovery_unit_test.cpp12
4 files changed, 19 insertions, 15 deletions
diff --git a/src/mongo/db/read_concern.cpp b/src/mongo/db/read_concern.cpp
index 6184548f7b0..d2f18637fac 100644
--- a/src/mongo/db/read_concern.cpp
+++ b/src/mongo/db/read_concern.cpp
@@ -206,10 +206,12 @@ Status waitForReadConcern(OperationContext* opCtx,
bool allowAfterClusterTime) {
// If we are in a direct client within a transaction, then we may be holding locks, so it is
// illegal to wait for read concern. This is fine, since the outer operation should have handled
- // waiting for read concern.
+ // waiting for read concern. We don't want to ignore prepare conflicts because snapshot reads
+ // should block on prepared transactions.
auto txnParticipant = TransactionParticipant::get(opCtx);
if (opCtx->getClient()->isInDirectClient() && txnParticipant &&
txnParticipant->inMultiDocumentTransaction()) {
+ opCtx->recoveryUnit()->setIgnorePrepared(false);
return Status::OK();
}
@@ -304,6 +306,8 @@ Status waitForReadConcern(OperationContext* opCtx,
}
if (atClusterTime) {
+ opCtx->recoveryUnit()->setIgnorePrepared(false);
+
// TODO(SERVER-34620): We should be using Session::setSpeculativeTransactionReadOpTime when
// doing speculative execution with atClusterTime.
opCtx->recoveryUnit()->setTimestampReadSource(RecoveryUnit::ReadSource::kProvided,
@@ -339,12 +343,12 @@ Status waitForReadConcern(OperationContext* opCtx,
}
// Only snapshot, linearizable and afterClusterTime reads should block on prepared transactions.
- // We don't ignore prepare conflicts if we are in a direct client in case this overrides
- // behavior set by a higher-level operation.
if (readConcernArgs.getLevel() != repl::ReadConcernLevel::kSnapshotReadConcern &&
readConcernArgs.getLevel() != repl::ReadConcernLevel::kLinearizableReadConcern &&
- !afterClusterTime && !atClusterTime && !opCtx->getClient()->isInDirectClient()) {
+ !afterClusterTime && !atClusterTime) {
opCtx->recoveryUnit()->setIgnorePrepared(true);
+ } else {
+ opCtx->recoveryUnit()->setIgnorePrepared(false);
}
return Status::OK();
diff --git a/src/mongo/db/storage/wiredtiger/wiredtiger_begin_transaction_block.h b/src/mongo/db/storage/wiredtiger/wiredtiger_begin_transaction_block.h
index 6052e1df6d3..73441b8f038 100644
--- a/src/mongo/db/storage/wiredtiger/wiredtiger_begin_transaction_block.h
+++ b/src/mongo/db/storage/wiredtiger/wiredtiger_begin_transaction_block.h
@@ -47,7 +47,7 @@ public:
// Whether or not to ignore prepared transactions.
enum class IgnorePrepared {
kNoIgnore, // Do not ignore prepared transactions and return prepare conflicts.
- kIgnore // Ignore prepared transactions and show prepared, but uncommitted data.
+ kIgnore // Ignore prepare conflicts, but don't show prepared data.
};
// Whether or not to round up to the oldest timestamp when the read timestamp is behind it.
@@ -57,7 +57,7 @@ public:
};
WiredTigerBeginTxnBlock(WT_SESSION* session,
- IgnorePrepared ignorePrepared = IgnorePrepared::kNoIgnore);
+ IgnorePrepared ignorePrepared = IgnorePrepared::kIgnore);
WiredTigerBeginTxnBlock(WT_SESSION* session, const char* config);
~WiredTigerBeginTxnBlock();
diff --git a/src/mongo/db/storage/wiredtiger/wiredtiger_recovery_unit.h b/src/mongo/db/storage/wiredtiger/wiredtiger_recovery_unit.h
index 585f01ece25..66c1e78033f 100644
--- a/src/mongo/db/storage/wiredtiger/wiredtiger_recovery_unit.h
+++ b/src/mongo/db/storage/wiredtiger/wiredtiger_recovery_unit.h
@@ -181,10 +181,10 @@ private:
// When 'true', data read from disk should not be kept in the storage engine cache.
bool _readOnce = false;
- // Ignoring prepared transactions will not return prepare conflicts and allow seeing prepared,
- // but uncommitted data.
+ // Ignoring prepared transactions will not return prepare conflicts and will not allow seeing
+ // prepared data.
WiredTigerBeginTxnBlock::IgnorePrepared _ignorePrepared{
- WiredTigerBeginTxnBlock::IgnorePrepared::kNoIgnore};
+ WiredTigerBeginTxnBlock::IgnorePrepared::kIgnore};
Timestamp _commitTimestamp;
Timestamp _prepareTimestamp;
boost::optional<Timestamp> _lastTimestampSet;
diff --git a/src/mongo/db/storage/wiredtiger/wiredtiger_recovery_unit_test.cpp b/src/mongo/db/storage/wiredtiger/wiredtiger_recovery_unit_test.cpp
index 63b0f95ee26..8e3cb105036 100644
--- a/src/mongo/db/storage/wiredtiger/wiredtiger_recovery_unit_test.cpp
+++ b/src/mongo/db/storage/wiredtiger/wiredtiger_recovery_unit_test.cpp
@@ -211,7 +211,7 @@ TEST_F(WiredTigerRecoveryUnitTestFixture, CreateAndCheckForCachePressure) {
}
TEST_F(WiredTigerRecoveryUnitTestFixture,
- LocalReadOnADocumentBeingPreparedTriggersPrepareConflict) {
+ LocalReadOnADocumentBeingPreparedWithoutIgnoringPreparedTriggersPrepareConflict) {
// Prepare but don't commit a transaction
ru1->beginUnitOfWork(clientAndCtx1.second.get());
WT_CURSOR* cursor;
@@ -222,8 +222,9 @@ TEST_F(WiredTigerRecoveryUnitTestFixture,
ru1->setPrepareTimestamp({1, 1});
ru1->prepareUnitOfWork();
- // Transaction read default triggers WT_PREPARE_CONFLICT
+ // Transaction read that does not ignore prepare conflicts triggers WT_PREPARE_CONFLICT
ru2->beginUnitOfWork(clientAndCtx2.second.get());
+ ru2->setIgnorePrepared(false);
getCursor(ru2, &cursor);
cursor->set_key(cursor, "key");
int ret = cursor->search(cursor);
@@ -234,7 +235,7 @@ TEST_F(WiredTigerRecoveryUnitTestFixture,
}
TEST_F(WiredTigerRecoveryUnitTestFixture,
- AvailableReadOnADocumentBeingPreparedDoesNotTriggerPrepareConflict) {
+ LocalReadOnADocumentBeingPreparedDoesntTriggerPrepareConflict) {
// Prepare but don't commit a transaction
ru1->beginUnitOfWork(clientAndCtx1.second.get());
WT_CURSOR* cursor;
@@ -245,10 +246,9 @@ TEST_F(WiredTigerRecoveryUnitTestFixture,
ru1->setPrepareTimestamp({1, 1});
ru1->prepareUnitOfWork();
- // Transaction that should ignore prepared transactions won't trigger
- // WT_PREPARE_CONFLICT
+ // Transaction read default ignores prepare conflicts but should not be able to read
+ // data from the prepared transaction.
ru2->beginUnitOfWork(clientAndCtx2.second.get());
- ru2->setIgnorePrepared(true);
getCursor(ru2, &cursor);
cursor->set_key(cursor, "key");
int ret = cursor->search(cursor);