diff options
author | Daniel Gottlieb <daniel.gottlieb@mongodb.com> | 2022-07-25 14:45:21 -0400 |
---|---|---|
committer | Evergreen Agent <no-reply@evergreen.mongodb.com> | 2022-07-26 17:57:14 +0000 |
commit | c90a8e578049d9921175fcd7db5f3e1becfa9076 (patch) | |
tree | d0567a9d61ea12801e13f225a95f837510287703 /src | |
parent | aa6a253f8b9c9023377870d47240784679077a0a (diff) | |
download | mongo-c90a8e578049d9921175fcd7db5f3e1becfa9076.tar.gz |
SERVER-65971: Have _restoreTxnsTableEntryFromRetryableWrites declare its intent as an untimestamped write.
Diffstat (limited to 'src')
20 files changed, 114 insertions, 56 deletions
diff --git a/src/mongo/db/index/index_build_interceptor.cpp b/src/mongo/db/index/index_build_interceptor.cpp index 6061ea3b90f..b27c7169d1a 100644 --- a/src/mongo/db/index/index_build_interceptor.cpp +++ b/src/mongo/db/index/index_build_interceptor.cpp @@ -162,6 +162,15 @@ Status IndexBuildInterceptor::drainWritesIntoIndex(OperationContext* opCtx, // Returns true if the cursor has reached the end of the table, false if there are more records, // and an error Status otherwise. auto applySingleBatch = [&]() -> StatusWith<bool> { + // This write is performed without a durable/commit timestamp. This transaction trips the + // ordered assertion for the side-table documents which are inserted with a timestamp and, + // in here, being deleted without a timestamp. Because the data being read is majority + // committed, there's no risk of needing to roll back the writes done by this "drain". + // + // Note that index builds will only "resume" once. A second resume results in the index + // build starting from scratch. A "resumed" index build does not use a majority read + // concern. And thus will observe data that can be rolled back via replication. + opCtx->recoveryUnit()->allowUntimestampedWrite(); WriteUnitOfWork wuow(opCtx); int32_t batchSize = 0; diff --git a/src/mongo/db/index_builds_coordinator.cpp b/src/mongo/db/index_builds_coordinator.cpp index 30b66e249b5..0c3cea6fc00 100644 --- a/src/mongo/db/index_builds_coordinator.cpp +++ b/src/mongo/db/index_builds_coordinator.cpp @@ -191,6 +191,11 @@ void removeIndexBuildEntryAfterCommitOrAbort(OperationContext* opCtx, return; } + if (replCoord->getSettings().shouldRecoverFromOplogAsStandalone()) { + // TODO SERVER-60753: Remove this mixed-mode write. + opCtx->recoveryUnit()->allowUntimestampedWrite(); + } + auto status = indexbuildentryhelpers::removeIndexBuildEntry( opCtx, indexBuildEntryCollection, replState.buildUUID); if (!status.isOK()) { @@ -545,6 +550,10 @@ Status IndexBuildsCoordinator::_startIndexBuildForRecovery(OperationContext* opC CollectionWriter collection(opCtx, nss); { + // TODO SERVER-64760: Remove this usage of `allowUntimestampedWrite`. We often have a valid + // timestamp for this write, but the callers of this function don't pass it through. + opCtx->recoveryUnit()->allowUntimestampedWrite(); + // These steps are combined into a single WUOW to ensure there are no commits without // the indexes. // 1) Drop all unfinished indexes. @@ -1880,6 +1889,12 @@ Status IndexBuildsCoordinator::_setUpIndexBuildForTwoPhaseRecovery( const UUID& buildUUID) { NamespaceStringOrUUID nssOrUuid{dbName.toString(), collectionUUID}; + if (opCtx->recoveryUnit()->isActive()) { + // This function is shared by multiple callers. Some of which have opened a transaction to + // perform reads. This function may make mixed-mode writes. Mixed-mode assertions can only + // be suppressed when beginning a fresh transaction. + opCtx->recoveryUnit()->abandonSnapshot(); + } // Don't use the AutoGet helpers because they require an open database, which may not be the // case when an index builds is restarted during recovery. @@ -2057,6 +2072,10 @@ IndexBuildsCoordinator::PostSetupAction IndexBuildsCoordinator::_setUpIndexBuild options.protocol = replState->protocol; try { + // TODO SERVER-64760: Remove this usage of `allowUntimestampedWrite`. There are cases where + // a timestamp is available to use, but the information is not passed through. + opCtx->recoveryUnit()->allowUntimestampedWrite(); + if (!replSetAndNotPrimary) { // On standalones and primaries, call setUpIndexBuild(), which makes the initial catalog // write. On primaries, this replicates the startIndexBuild oplog entry. diff --git a/src/mongo/db/repair.cpp b/src/mongo/db/repair.cpp index c880b32487b..a6f8029be24 100644 --- a/src/mongo/db/repair.cpp +++ b/src/mongo/db/repair.cpp @@ -71,6 +71,13 @@ using namespace fmt::literals; Status rebuildIndexesForNamespace(OperationContext* opCtx, const NamespaceString& nss, StorageEngine* engine) { + if (opCtx->recoveryUnit()->isActive()) { + // This function is shared by multiple callers. Some of which have opened a transaction to + // perform reads. This function may make mixed-mode writes. Mixed-mode assertions can only + // be suppressed when beginning a fresh transaction. + opCtx->recoveryUnit()->abandonSnapshot(); + } + opCtx->checkForInterrupt(); auto collection = CollectionCatalog::get(opCtx)->lookupCollectionByNamespace(opCtx, nss); auto swIndexNameObjs = getIndexNameObjs(collection); diff --git a/src/mongo/db/repl/oplog_applier_impl_test.cpp b/src/mongo/db/repl/oplog_applier_impl_test.cpp index 88eb0fb7fb7..ef1767ee934 100644 --- a/src/mongo/db/repl/oplog_applier_impl_test.cpp +++ b/src/mongo/db/repl/oplog_applier_impl_test.cpp @@ -2683,6 +2683,11 @@ public: void setUp() override { OplogApplierImplTest::setUp(); + // This fixture sets up some replication, but notably omits installing an + // OpObserverImpl. This state causes collection creation to timestamp catalog writes, but + // secondary index creation does not. We use an UnreplicatedWritesBlock to avoid + // timestamping any of the catalog setup. + repl::UnreplicatedWritesBlock noRep(_opCtx.get()); MongoDSessionCatalog::onStepUp(_opCtx.get()); DBDirectClient client(_opCtx.get()); diff --git a/src/mongo/db/repl/oplog_applier_impl_test_fixture.cpp b/src/mongo/db/repl/oplog_applier_impl_test_fixture.cpp index 72c93034d8b..7c3d062a545 100644 --- a/src/mongo/db/repl/oplog_applier_impl_test_fixture.cpp +++ b/src/mongo/db/repl/oplog_applier_impl_test_fixture.cpp @@ -503,6 +503,10 @@ void createIndex(OperationContext* opCtx, Lock::DBLock dbLk(opCtx, nss.dbName(), MODE_IX); Lock::CollectionLock collLk(opCtx, nss, MODE_X); auto indexBuildsCoord = IndexBuildsCoordinator::get(opCtx); + // This fixture sets up some replication, but notably omits installing an OpObserverImpl. This + // state causes collection creation to timestamp catalog writes, but secondary index creation + // does not. We use an UnreplicatedWritesBlock to avoid timestamping any of the catalog setup. + repl::UnreplicatedWritesBlock noRep(opCtx); indexBuildsCoord->createIndex( opCtx, collUUID, spec, IndexBuildsManager::IndexConstraints::kEnforce, false); } diff --git a/src/mongo/db/repl/oplog_applier_test.cpp b/src/mongo/db/repl/oplog_applier_test.cpp index cb35f041caa..d9eff0fced7 100644 --- a/src/mongo/db/repl/oplog_applier_test.cpp +++ b/src/mongo/db/repl/oplog_applier_test.cpp @@ -369,6 +369,7 @@ public: void setUp() override { OplogApplierTest::setUp(); auto* service = getServiceContext(); + _origThreadName = *getThreadNameRef().get(); Client::initThread("OplogApplierDelayTest", service, nullptr); _mockClock = std::make_shared<ClockSourceMock>(); @@ -387,6 +388,7 @@ public: _opCtxHolder = nullptr; Client::releaseCurrent(); OplogApplierTest::tearDown(); + setThreadName(_origThreadName); } OperationContext* opCtx() override { @@ -412,6 +414,9 @@ protected: std::shared_ptr<ClockSourceMock> _mockClock; ServiceContext::UniqueOperationContext _opCtxHolder; AtomicWord<bool> _failWaits{false}; + +private: + std::string _origThreadName; }; TEST_F(OplogApplierDelayTest, GetNextApplierBatchReturnsEmptyBatchImmediately) { diff --git a/src/mongo/db/repl/replication_recovery_test.cpp b/src/mongo/db/repl/replication_recovery_test.cpp index dc2287e9f03..b31925a330a 100644 --- a/src/mongo/db/repl/replication_recovery_test.cpp +++ b/src/mongo/db/repl/replication_recovery_test.cpp @@ -195,10 +195,17 @@ private: repl::createOplog(_opCtx.get()); - ASSERT_OK(_storageInterface->createCollection( - getOperationContext(), testNs, generateOptionsWithUuid())); - - MongoDSessionCatalog::onStepUp(_opCtx.get()); + { + // This fixture sets up some replication, but notably omits installing an + // OpObserverImpl. This state causes collection creation to timestamp catalog writes, + // but secondary index creation does not. We use an UnreplicatedWritesBlock to avoid + // timestamping any of the catalog setup. + repl::UnreplicatedWritesBlock noRep(_opCtx.get()); + ASSERT_OK(_storageInterface->createCollection( + getOperationContext(), testNs, generateOptionsWithUuid())); + + MongoDSessionCatalog::onStepUp(_opCtx.get()); + } auto observerRegistry = checked_cast<OpObserverRegistry*>(service->getOpObserver()); observerRegistry->addObserver(std::make_unique<ReplicationRecoveryTestObObserver>()); diff --git a/src/mongo/db/repl/rollback_impl.cpp b/src/mongo/db/repl/rollback_impl.cpp index 91893402542..613518af43b 100644 --- a/src/mongo/db/repl/rollback_impl.cpp +++ b/src/mongo/db/repl/rollback_impl.cpp @@ -524,6 +524,7 @@ void RollbackImpl::_restoreTxnsTableEntryFromRetryableWrites(OperationContext* o } const auto nss = NamespaceString::kSessionTransactionsTableNamespace; writeConflictRetry(opCtx, "updateSessionTransactionsTableInRollback", nss.ns(), [&] { + opCtx->recoveryUnit()->allowUntimestampedWrite(); AutoGetCollection collection(opCtx, nss, MODE_IX); auto filter = BSON(SessionTxnRecord::kSessionIdFieldName << sessionId.toBSON()); UnreplicatedWritesBlock uwb(opCtx); diff --git a/src/mongo/db/repl/storage_timestamp_test.cpp b/src/mongo/db/repl/storage_timestamp_test.cpp index 299bfcc2339..4f3f5bf0a18 100644 --- a/src/mongo/db/repl/storage_timestamp_test.cpp +++ b/src/mongo/db/repl/storage_timestamp_test.cpp @@ -137,7 +137,8 @@ Status createIndexFromSpec(OperationContext* opCtx, collection, spec, [opCtx, clock](const std::vector<BSONObj>& specs) -> Status { - if (opCtx->recoveryUnit()->getCommitTimestamp().isNull()) { + if (opCtx->writesAreReplicated() && + opCtx->recoveryUnit()->getCommitTimestamp().isNull()) { return opCtx->recoveryUnit()->setTimestamp( clock->tickClusterTime(1).asTimestamp()); } @@ -167,8 +168,10 @@ Status createIndexFromSpec(OperationContext* opCtx, collection.getWritableCollection(opCtx), MultiIndexBlock::kNoopOnCreateEachFn, MultiIndexBlock::kNoopOnCommitFn)); - LogicalTime indexTs = clock->tickClusterTime(1); - ASSERT_OK(opCtx->recoveryUnit()->setTimestamp(indexTs.asTimestamp())); + if (opCtx->writesAreReplicated()) { + LogicalTime indexTs = clock->tickClusterTime(1); + ASSERT_OK(opCtx->recoveryUnit()->setTimestamp(indexTs.asTimestamp())); + } wunit.commit(); abortOnExit.dismiss(); return Status::OK(); @@ -356,7 +359,8 @@ public: AutoGetCollection autoColl(_opCtx, nss, LockMode::MODE_IX); auto db = autoColl.ensureDbExists(_opCtx); WriteUnitOfWork wunit(_opCtx); - if (_opCtx->recoveryUnit()->getCommitTimestamp().isNull()) { + if (_opCtx->writesAreReplicated() && + _opCtx->recoveryUnit()->getCommitTimestamp().isNull()) { ASSERT_OK(_opCtx->recoveryUnit()->setTimestamp(Timestamp(1, 1))); } invariant(db->createCollection(_opCtx, nss)); @@ -1666,6 +1670,7 @@ TEST_F(StorageTimestampTest, PrimarySetIndexMultikeyOnInsert) { TEST_F(StorageTimestampTest, PrimarySetIndexMultikeyOnInsertUnreplicated) { // Use an unreplicated collection. + repl::UnreplicatedWritesBlock noRep(_opCtx); NamespaceString nss("unittests.system.profile"); create(nss); diff --git a/src/mongo/db/service_context_d_test_fixture.cpp b/src/mongo/db/service_context_d_test_fixture.cpp index 0e40005bde4..caef9950914 100644 --- a/src/mongo/db/service_context_d_test_fixture.cpp +++ b/src/mongo/db/service_context_d_test_fixture.cpp @@ -70,6 +70,11 @@ ServiceContextMongoDTest::ServiceContextMongoDTest(Options options) replSettings.setOplogSizeBytes(10 * 1024 * 1024); replSettings.setReplSetString("rs0"); setGlobalReplSettings(replSettings); + } else { + repl::ReplSettings replSettings; + // The empty string "disables" replication. + replSettings.setReplSetString(""); + setGlobalReplSettings(replSettings); } _stashedStorageParams.engine = diff --git a/src/mongo/db/storage/recovery_unit.h b/src/mongo/db/storage/recovery_unit.h index 6ac1a4375c6..fed9d478540 100644 --- a/src/mongo/db/storage/recovery_unit.h +++ b/src/mongo/db/storage/recovery_unit.h @@ -409,6 +409,12 @@ public: return {}; } + /** + * MongoDB must update documents with non-decreasing timestamp values. A storage engine is + * allowed to assert when this contract is violated. An untimestamped write is a subset of these + * violations, which may be necessary in limited circumstances. This API can be called before a + * transaction begins to suppress this subset of errors. + */ virtual void allowUntimestampedWrite() {} /** diff --git a/src/mongo/db/storage/wiredtiger/wiredtiger_begin_transaction_block.cpp b/src/mongo/db/storage/wiredtiger/wiredtiger_begin_transaction_block.cpp index e91b228505a..abb0617c124 100644 --- a/src/mongo/db/storage/wiredtiger/wiredtiger_begin_transaction_block.cpp +++ b/src/mongo/db/storage/wiredtiger/wiredtiger_begin_transaction_block.cpp @@ -49,7 +49,7 @@ WiredTigerBeginTxnBlock::WiredTigerBeginTxnBlock( PrepareConflictBehavior prepareConflictBehavior, RoundUpPreparedTimestamps roundUpPreparedTimestamps, RoundUpReadTimestamp roundUpReadTimestamp, - bool allowUntimestampedWrite) + UntimestampedWriteAssertion allowUntimestampedWrite) : _session(session) { invariant(!_rollback); @@ -70,7 +70,7 @@ WiredTigerBeginTxnBlock::WiredTigerBeginTxnBlock( } builder << "),"; } - if (allowUntimestampedWrite) { + if (allowUntimestampedWrite == UntimestampedWriteAssertion::kSuppress) { builder << "no_timestamp=true,"; } 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 ed9b7789be0..4faf831727e 100644 --- a/src/mongo/db/storage/wiredtiger/wiredtiger_begin_transaction_block.h +++ b/src/mongo/db/storage/wiredtiger/wiredtiger_begin_transaction_block.h @@ -58,12 +58,13 @@ public: // earlier. enum class RoundUpPreparedTimestamps { kNoRound, kRound }; - WiredTigerBeginTxnBlock( - WT_SESSION* session, - PrepareConflictBehavior prepareConflictBehavior, - RoundUpPreparedTimestamps roundUpPreparedTimestamps, - RoundUpReadTimestamp roundUpReadTimestamp, - bool allowUntimestampedWrite); + enum class UntimestampedWriteAssertion { kSuppress, kEnforce }; + + WiredTigerBeginTxnBlock(WT_SESSION* session, + PrepareConflictBehavior prepareConflictBehavior, + RoundUpPreparedTimestamps roundUpPreparedTimestamps, + RoundUpReadTimestamp roundUpReadTimestamp, + UntimestampedWriteAssertion allowUntimestampedWrite); WiredTigerBeginTxnBlock(WT_SESSION* session, const char* config); ~WiredTigerBeginTxnBlock(); diff --git a/src/mongo/db/storage/wiredtiger/wiredtiger_begin_transaction_block_bm.cpp b/src/mongo/db/storage/wiredtiger/wiredtiger_begin_transaction_block_bm.cpp index 7033ff3931a..3557b8d29fa 100644 --- a/src/mongo/db/storage/wiredtiger/wiredtiger_begin_transaction_block_bm.cpp +++ b/src/mongo/db/storage/wiredtiger/wiredtiger_begin_transaction_block_bm.cpp @@ -127,13 +127,13 @@ using mongo::WiredTigerBeginTxnBlock; template <PrepareConflictBehavior behavior, RoundUpPreparedTimestamps round> void BM_WiredTigerBeginTxnBlockWithArgs(benchmark::State& state) { WiredTigerTestHelper helper; - const bool allowUntimestampedWrite = false; for (auto _ : state) { - WiredTigerBeginTxnBlock beginTxn(helper.wtSession(), - behavior, - round, - RoundUpReadTimestamp::kNoRoundError, - allowUntimestampedWrite); + WiredTigerBeginTxnBlock beginTxn( + helper.wtSession(), + behavior, + round, + RoundUpReadTimestamp::kNoRoundError, + WiredTigerBeginTxnBlock::UntimestampedWriteAssertion::kEnforce); } } diff --git a/src/mongo/db/storage/wiredtiger/wiredtiger_index.cpp b/src/mongo/db/storage/wiredtiger/wiredtiger_index.cpp index 5714609a722..df275526c30 100644 --- a/src/mongo/db/storage/wiredtiger/wiredtiger_index.cpp +++ b/src/mongo/db/storage/wiredtiger/wiredtiger_index.cpp @@ -162,12 +162,7 @@ StatusWith<std::string> WiredTigerIndex::generateCreateString( ss << "prefix_compression=true,"; } - if ( // TODO (SERVER-60753): Remove special handling for index build during recovery. - collectionNamespace.ns() == "config.system.indexBuilds") { - ss << "write_timestamp_usage=mixed_mode,"; - } else { - ss << "write_timestamp_usage=ordered,"; - } + // Report errors on writes without ordered timestamps. ss << "assert=(write_timestamp=on),"; ss << "verbose=[write_timestamp],"; diff --git a/src/mongo/db/storage/wiredtiger/wiredtiger_record_store.cpp b/src/mongo/db/storage/wiredtiger/wiredtiger_record_store.cpp index 5481f840590..e05ae7ae795 100644 --- a/src/mongo/db/storage/wiredtiger/wiredtiger_record_store.cpp +++ b/src/mongo/db/storage/wiredtiger/wiredtiger_record_store.cpp @@ -796,20 +796,7 @@ StatusWith<std::string> WiredTigerRecordStore::generateCreateString( ss << "split_pct=90,"; ss << "leaf_value_max=64MB,"; - if (nss.isOplog()) { - // For the above clauses we do not assert any particular `write_timestamp_usage`. In - // particular for the oplog, WT removes all timestamp information. There's nothing in - // MDB's control to assert against. - } else if ( - // Side table drains are not timestamped. - ident.startsWith("internal-") || - // TODO (SERVER-60753): Remove special handling for index build during recovery. This - // includes the following _mdb_catalog ident. - nss == NamespaceString::kIndexBuildEntryNamespace || ident.startsWith("_mdb_catalog")) { - ss << "write_timestamp_usage=mixed_mode,"; - } else { - ss << "write_timestamp_usage=ordered,"; - } + // Report errors on writes without ordered timestamps. ss << "assert=(write_timestamp=on),"; ss << "verbose=[write_timestamp],"; diff --git a/src/mongo/db/storage/wiredtiger/wiredtiger_recovery_unit.cpp b/src/mongo/db/storage/wiredtiger/wiredtiger_recovery_unit.cpp index 4d93dbd3c17..e121856c916 100644 --- a/src/mongo/db/storage/wiredtiger/wiredtiger_recovery_unit.cpp +++ b/src/mongo/db/storage/wiredtiger/wiredtiger_recovery_unit.cpp @@ -520,7 +520,7 @@ void WiredTigerRecoveryUnit::_txnClose(bool commit) { _isOplogReader = false; _oplogVisibleTs = boost::none; _orderedCommit = true; // Default value is true; we assume all writes are ordered. - _allowUntimestampedWrite = false; + _untimestampedWriteAssertion = WiredTigerBeginTxnBlock::UntimestampedWriteAssertion::kEnforce; } Status WiredTigerRecoveryUnit::majorityCommittedSnapshotAvailable() const { @@ -611,7 +611,7 @@ void WiredTigerRecoveryUnit::_txnOpen() { _prepareConflictBehavior, _roundUpPreparedTimestamps, RoundUpReadTimestamp::kNoRoundError, - _allowUntimestampedWrite) + _untimestampedWriteAssertion) .done(); break; } @@ -620,7 +620,7 @@ void WiredTigerRecoveryUnit::_txnOpen() { session, _prepareConflictBehavior, _roundUpPreparedTimestamps, - _allowUntimestampedWrite); + _untimestampedWriteAssertion); break; } case ReadSource::kLastApplied: { @@ -643,7 +643,7 @@ void WiredTigerRecoveryUnit::_txnOpen() { _prepareConflictBehavior, _roundUpPreparedTimestamps, RoundUpReadTimestamp::kNoRoundError, - _allowUntimestampedWrite); + _untimestampedWriteAssertion); auto status = txnOpen.setReadSnapshot(_readAtTimestamp); if (!status.isOK() && status.code() == ErrorCodes::BadValue) { @@ -672,7 +672,7 @@ Timestamp WiredTigerRecoveryUnit::_beginTransactionAtAllDurableTimestamp(WT_SESS _prepareConflictBehavior, _roundUpPreparedTimestamps, RoundUpReadTimestamp::kRound, - _allowUntimestampedWrite); + _untimestampedWriteAssertion); Timestamp txnTimestamp = _sessionCache->getKVEngine()->getAllDurableTimestamp(); auto status = txnOpen.setReadSnapshot(txnTimestamp); fassert(50948, status); @@ -700,7 +700,7 @@ void WiredTigerRecoveryUnit::_beginTransactionAtLastAppliedTimestamp(WT_SESSION* _prepareConflictBehavior, _roundUpPreparedTimestamps, RoundUpReadTimestamp::kNoRoundError, - _allowUntimestampedWrite); + _untimestampedWriteAssertion); LOGV2_DEBUG(4847500, 2, "no read timestamp available for kLastApplied"); txnOpen.done(); return; @@ -710,7 +710,7 @@ void WiredTigerRecoveryUnit::_beginTransactionAtLastAppliedTimestamp(WT_SESSION* _prepareConflictBehavior, _roundUpPreparedTimestamps, RoundUpReadTimestamp::kRound, - _allowUntimestampedWrite); + _untimestampedWriteAssertion); auto status = txnOpen.setReadSnapshot(_readAtTimestamp); fassert(4847501, status); @@ -766,7 +766,7 @@ Timestamp WiredTigerRecoveryUnit::_beginTransactionAtNoOverlapTimestamp(WT_SESSI _prepareConflictBehavior, _roundUpPreparedTimestamps, RoundUpReadTimestamp::kNoRoundError, - _allowUntimestampedWrite); + _untimestampedWriteAssertion); LOGV2_DEBUG(4452900, 1, "no read timestamp available for kNoOverlap"); txnOpen.done(); return readTimestamp; @@ -776,7 +776,7 @@ Timestamp WiredTigerRecoveryUnit::_beginTransactionAtNoOverlapTimestamp(WT_SESSI _prepareConflictBehavior, _roundUpPreparedTimestamps, RoundUpReadTimestamp::kRound, - _allowUntimestampedWrite); + _untimestampedWriteAssertion); auto status = txnOpen.setReadSnapshot(readTimestamp); fassert(51066, status); diff --git a/src/mongo/db/storage/wiredtiger/wiredtiger_recovery_unit.h b/src/mongo/db/storage/wiredtiger/wiredtiger_recovery_unit.h index c16a6ce9b29..5397b91fb91 100644 --- a/src/mongo/db/storage/wiredtiger/wiredtiger_recovery_unit.h +++ b/src/mongo/db/storage/wiredtiger/wiredtiger_recovery_unit.h @@ -150,7 +150,8 @@ public: void allowUntimestampedWrite() override { invariant(!_isActive()); - _allowUntimestampedWrite = true; + _untimestampedWriteAssertion = + WiredTigerBeginTxnBlock::UntimestampedWriteAssertion::kSuppress; } void setTimestampReadSource(ReadSource source, @@ -316,7 +317,8 @@ private: boost::optional<Timestamp> _lastTimestampSet; Timestamp _readAtTimestamp; Timestamp _catalogConflictTimestamp; - bool _allowUntimestampedWrite = false; + WiredTigerBeginTxnBlock::UntimestampedWriteAssertion _untimestampedWriteAssertion = + WiredTigerBeginTxnBlock::UntimestampedWriteAssertion::kEnforce; std::unique_ptr<Timer> _timer; bool _isOplogReader = false; boost::optional<int64_t> _oplogVisibleTs = boost::none; diff --git a/src/mongo/db/storage/wiredtiger/wiredtiger_snapshot_manager.cpp b/src/mongo/db/storage/wiredtiger/wiredtiger_snapshot_manager.cpp index 2e093d59ea1..819e19992ca 100644 --- a/src/mongo/db/storage/wiredtiger/wiredtiger_snapshot_manager.cpp +++ b/src/mongo/db/storage/wiredtiger/wiredtiger_snapshot_manager.cpp @@ -84,7 +84,7 @@ Timestamp WiredTigerSnapshotManager::beginTransactionOnCommittedSnapshot( WT_SESSION* session, PrepareConflictBehavior prepareConflictBehavior, RoundUpPreparedTimestamps roundUpPreparedTimestamps, - bool allowUntimestampedWrite) const { + WiredTigerBeginTxnBlock::UntimestampedWriteAssertion untimestampedWriteAssertion) const { auto committedSnapshot = [this]() { stdx::lock_guard<Latch> lock(_committedSnapshotMutex); @@ -104,7 +104,7 @@ Timestamp WiredTigerSnapshotManager::beginTransactionOnCommittedSnapshot( prepareConflictBehavior, roundUpPreparedTimestamps, RoundUpReadTimestamp::kRound, - allowUntimestampedWrite); + untimestampedWriteAssertion); auto status = txnOpen.setReadSnapshot(committedSnapshot); fassert(30635, status); diff --git a/src/mongo/db/storage/wiredtiger/wiredtiger_snapshot_manager.h b/src/mongo/db/storage/wiredtiger/wiredtiger_snapshot_manager.h index 088bf7a50f9..b3cf9b4d030 100644 --- a/src/mongo/db/storage/wiredtiger/wiredtiger_snapshot_manager.h +++ b/src/mongo/db/storage/wiredtiger/wiredtiger_snapshot_manager.h @@ -68,7 +68,7 @@ public: WT_SESSION* session, PrepareConflictBehavior prepareConflictBehavior, RoundUpPreparedTimestamps roundUpPreparedTimestamps, - bool allowUntimestampedWrite) const; + WiredTigerBeginTxnBlock::UntimestampedWriteAssertion untimestampedWriteAssertion) const; /** * Returns lowest SnapshotName that could possibly be used by a future call to |