From f5ad04df2255518e16048e09dcf2baeff64bd7a8 Mon Sep 17 00:00:00 2001 From: Louis Williams Date: Wed, 11 Nov 2020 09:23:44 -0500 Subject: Revert "SERVER-48002 Do not enforce DataCorruptionDetected assertion when ignoring prepare conflicts" This reverts commit 523247d096a796c15c911370e622a3614411a25b. --- jstests/replsets/query_with_txn_prepared.js | 63 ----------------------------- src/mongo/db/exec/working_set_common.cpp | 7 +--- 2 files changed, 1 insertion(+), 69 deletions(-) delete mode 100644 jstests/replsets/query_with_txn_prepared.js diff --git a/jstests/replsets/query_with_txn_prepared.js b/jstests/replsets/query_with_txn_prepared.js deleted file mode 100644 index fcf05002310..00000000000 --- a/jstests/replsets/query_with_txn_prepared.js +++ /dev/null @@ -1,63 +0,0 @@ -/** - * This test attempts to reproduce the bug described in SERVER-48002. This is a best-effort test - * that will not detect this bug on every run, even if a bug exists. - * - * Snapshot isolation cannot be guaranteed for operations that ignore prepare conflicts. - * This means that two reads of the same record in the same snapshot can return different results. - * In practice, the DataCorruptionDetected assertion added by SERVER-40620 will trigger if an index - * points to a non-existent record. - * - * Queries that ignore prepare conflicts and use an index to satisfy a read can read a key from an - * index and fetch a record that appears to go missing within the same snapshot. This may happen - * when the collection read races with a prepared transaction that commits and deletes the record. - * - * - * @tags: [ - * uses_prepare_transaction, - * uses_transactions, - * ] - */ -(function() { -"use strict"; - -const replTest = new ReplSetTest({nodes: 2}); -replTest.startSet(); -replTest.initiate(); - -const primary = replTest.getPrimary(); -const dbName = "query_with_txn_prepared"; -const collName = "coll"; - -assert.commandWorked(primary.getDB(dbName)[collName].createIndexes([{x: 1}])); - -const transactionShell = startParallelShell(function() { - load("jstests/core/txns/libs/prepare_helpers.js"); // For PrepareHelpers. - - while (db.getSiblingDB("query_with_txn_prepared")["stopQueries"].find().count() == 0) { - for (let i = 0; i < 100; ++i) { - const session = db.getMongo().startSession(); - const sessionColl = session.getDatabase("query_with_txn_prepared")["coll"]; - - session.startTransaction({readConcern: {level: "majority"}}); - if (Math.random() < 0.5) { - assert.commandWorked(sessionColl.update({x: 1}, {x: 1}, {upsert: true})); - } else { - assert.commandWorked(sessionColl.remove({x: 1})); - } - - const prepareTimestamp = PrepareHelpers.prepareTransaction(session); - assert.commandWorked(PrepareHelpers.commitTransaction(session, prepareTimestamp)); - } - } -}, primary.port); - -for (let i = 0; i < 2000; ++i) { - const result = primary.getDB(dbName)[collName].find({x: 1}).toArray(); - assert([0, 1].includes(result.length), result); -} - -assert.commandWorked(primary.getDB(dbName)["stopQueries"].insert({stop: 1})); -transactionShell(); - -replTest.stopSet(); -}()); diff --git a/src/mongo/db/exec/working_set_common.cpp b/src/mongo/db/exec/working_set_common.cpp index 33a9f6074e7..c6083642478 100644 --- a/src/mongo/db/exec/working_set_common.cpp +++ b/src/mongo/db/exec/working_set_common.cpp @@ -82,14 +82,9 @@ bool WorkingSetCommon::fetch(OperationContext* opCtx, // The record referenced by this index entry is gone. If the query yielded some time after // we first examined the index entry, then it's likely that the record was deleted while we // were yielding. However, if the snapshot id hasn't changed since the index lookup, then - // there could not have been a yield, meaning the document we are searching for has been - // deleted. - // One possibility is that the record was deleted by a prepared transaction, but if we are - // not ignoring prepare conflicts, then this definitely indicates an error. + // there could not have been a yield, and the only explanation is corruption. std::vector::iterator keyDataIt; if (member->getState() == WorkingSetMember::RID_AND_IDX && - opCtx->recoveryUnit()->getPrepareConflictBehavior() == - PrepareConflictBehavior::kEnforce && (keyDataIt = std::find_if(member->keyData.begin(), member->keyData.end(), [currentSnapshotId = opCtx->recoveryUnit()->getSnapshotId()]( -- cgit v1.2.1