mirror of
https://github.com/mongodb/mongo.git
synced 2024-12-01 01:21:03 +01:00
SERVER-39672: default to local if no read concern specified for a multi-statment transaction
This commit is contained in:
parent
109129eb5f
commit
74fd169e88
@ -22,15 +22,21 @@
|
||||
assert.commandWorked(testDB.createCollection(collName2, {writeConcern: {w: "majority"}}));
|
||||
|
||||
const sessionOptions = {causalConsistency: false};
|
||||
const session = db.getMongo().startSession(sessionOptions);
|
||||
const sessionDb = session.getDatabase(dbName);
|
||||
const sessionColl = sessionDb.getCollection(collName);
|
||||
const sessionColl2 = sessionDb.getCollection(collName2);
|
||||
|
||||
const session2 = db.getMongo().startSession(sessionOptions);
|
||||
const session2Db = session2.getDatabase(dbName);
|
||||
const session2Coll = session2Db.getCollection(collName);
|
||||
const session2Coll2 = session2Db.getCollection(collName2);
|
||||
function startSessionAndTransaction(readConcernLevel) {
|
||||
let session = db.getMongo().startSession(sessionOptions);
|
||||
jsTestLog("Start a transaction with readConcern " + readConcernLevel.level + ".");
|
||||
session.startTransaction({readConcern: readConcernLevel});
|
||||
return session;
|
||||
};
|
||||
|
||||
let checkReads = (session, collExpected, coll2Expected) => {
|
||||
let sessionDb = session.getDatabase(dbName);
|
||||
let coll = sessionDb.getCollection(collName);
|
||||
let coll2 = sessionDb.getCollection(collName2);
|
||||
assert.sameMembers(collExpected, coll.find().toArray());
|
||||
assert.sameMembers(coll2Expected, coll2.find().toArray());
|
||||
};
|
||||
|
||||
// Clear ramlog so checkLog can't find log messages from previous times this fail point was
|
||||
// enabled.
|
||||
@ -63,21 +69,17 @@
|
||||
// the prior uncommitted write is committed.
|
||||
assert.commandWorked(testColl.insert([{_id: 1}]));
|
||||
|
||||
jsTestLog("Start a snapshot transaction.");
|
||||
const snapshotSession = startSessionAndTransaction({level: "snapshot"});
|
||||
checkReads(snapshotSession, [{_id: 0}], [{_id: "a"}]);
|
||||
|
||||
session.startTransaction({readConcern: {level: "snapshot"}});
|
||||
const majoritySession = startSessionAndTransaction({level: "majority"});
|
||||
checkReads(majoritySession, [{_id: 0}, {_id: 1}], [{_id: "a"}]);
|
||||
|
||||
assert.sameMembers([{_id: 0}], sessionColl.find().toArray());
|
||||
const localSession = startSessionAndTransaction({level: "local"});
|
||||
checkReads(localSession, [{_id: 0}, {_id: 1}], [{_id: "a"}]);
|
||||
|
||||
assert.sameMembers([{_id: "a"}], sessionColl2.find().toArray());
|
||||
|
||||
jsTestLog("Start a majority-read transaction.");
|
||||
|
||||
session2.startTransaction({readConcern: {level: "majority"}});
|
||||
|
||||
assert.sameMembers([{_id: 0}, {_id: 1}], session2Coll.find().toArray());
|
||||
|
||||
assert.sameMembers([{_id: "a"}], session2Coll2.find().toArray());
|
||||
const defaultSession = startSessionAndTransaction({});
|
||||
checkReads(defaultSession, [{_id: 0}, {_id: 1}], [{_id: "a"}]);
|
||||
|
||||
jsTestLog("Allow the uncommitted write to finish.");
|
||||
assert.commandWorked(db.adminCommand({
|
||||
@ -88,25 +90,25 @@
|
||||
joinHungWrite();
|
||||
|
||||
jsTestLog("Double-checking that writes not committed at start of snapshot cannot appear.");
|
||||
assert.sameMembers([{_id: 0}], sessionColl.find().toArray());
|
||||
checkReads(snapshotSession, [{_id: 0}], [{_id: "a"}]);
|
||||
|
||||
assert.sameMembers([{_id: "a"}], sessionColl2.find().toArray());
|
||||
|
||||
assert.sameMembers([{_id: 0}, {_id: 1}], session2Coll.find().toArray());
|
||||
|
||||
assert.sameMembers([{_id: "a"}], session2Coll2.find().toArray());
|
||||
jsTestLog(
|
||||
"Double-checking that writes performed before the start of a transaction of 'majority' or lower must appear.");
|
||||
checkReads(majoritySession, [{_id: 0}, {_id: 1}], [{_id: "a"}]);
|
||||
checkReads(localSession, [{_id: 0}, {_id: 1}], [{_id: "a"}]);
|
||||
checkReads(defaultSession, [{_id: 0}, {_id: 1}], [{_id: "a"}]);
|
||||
|
||||
jsTestLog("Committing transactions.");
|
||||
session.commitTransaction();
|
||||
session2.commitTransaction();
|
||||
snapshotSession.commitTransaction();
|
||||
majoritySession.commitTransaction();
|
||||
localSession.commitTransaction();
|
||||
defaultSession.commitTransaction();
|
||||
|
||||
assert.sameMembers([{_id: 0}, {_id: 1}], sessionColl.find().toArray());
|
||||
jsTestLog("A new local read must see all committed writes.");
|
||||
checkReads(defaultSession, [{_id: 0}, {_id: 1}], [{_id: "a"}, {_id: "b"}]);
|
||||
|
||||
assert.sameMembers([{_id: "a"}, {_id: "b"}], sessionColl2.find().toArray());
|
||||
|
||||
assert.sameMembers([{_id: 0}, {_id: 1}], session2Coll.find().toArray());
|
||||
|
||||
assert.sameMembers([{_id: "a"}, {_id: "b"}], session2Coll2.find().toArray());
|
||||
|
||||
session.endSession();
|
||||
snapshotSession.endSession();
|
||||
majoritySession.endSession();
|
||||
localSession.endSession();
|
||||
defaultSession.endSession();
|
||||
}());
|
||||
|
@ -71,7 +71,7 @@
|
||||
jsTest.log("Start a transaction and then commit it.");
|
||||
|
||||
// Compare server status after starting a transaction with the server status before.
|
||||
session.startTransaction();
|
||||
session.startTransaction({readConcern: {level: 'snapshot'}});
|
||||
assert.commandWorked(sessionColl.insert({_id: "insert-1"}));
|
||||
// Trigger the oldestOpenUnpreparedReadTimestamp to be set.
|
||||
assert.eq(sessionColl.find({_id: "insert-1"}).itcount(), 1);
|
||||
@ -110,7 +110,7 @@
|
||||
jsTest.log("Start a transaction and then abort it.");
|
||||
|
||||
// Compare server status after starting a transaction with the server status before.
|
||||
session.startTransaction();
|
||||
session.startTransaction({readConcern: {level: 'snapshot'}});
|
||||
assert.commandWorked(sessionColl.insert({_id: "insert-2"}));
|
||||
// Trigger the oldestOpenUnpreparedReadTimestamp to be set.
|
||||
assert.eq(sessionColl.find({_id: "insert-2"}).itcount(), 1);
|
||||
@ -150,7 +150,7 @@
|
||||
jsTest.log("Start a transaction that will abort on a duplicated key error.");
|
||||
|
||||
// Compare server status after starting a transaction with the server status before.
|
||||
session.startTransaction();
|
||||
session.startTransaction({readConcern: {level: 'snapshot'}});
|
||||
// Inserting a new document will work fine, and the transaction starts.
|
||||
assert.commandWorked(sessionColl.insert({_id: "insert-3"}));
|
||||
// Trigger the oldestOpenUnpreparedReadTimestamp to be set.
|
||||
|
@ -69,7 +69,7 @@
|
||||
const doc1 = {_id: 1, x: 1};
|
||||
|
||||
// Start transaction and prepare transaction.
|
||||
session.startTransaction();
|
||||
session.startTransaction({readConcern: {level: 'snapshot'}});
|
||||
assert.commandWorked(sessionColl.insert(doc1));
|
||||
|
||||
// Trigger the oldestOpenUnpreparedReadTimestamp to be set.
|
||||
@ -118,7 +118,7 @@
|
||||
const doc2 = {_id: 2, x: 2};
|
||||
|
||||
// Start transaction and prepare transaction.
|
||||
session.startTransaction();
|
||||
session.startTransaction({readConcern: {level: 'snapshot'}});
|
||||
assert.commandWorked(sessionColl.insert(doc2));
|
||||
|
||||
// Trigger the oldestOpenUnpreparedReadTimestamp to be set.
|
||||
|
@ -35,7 +35,7 @@
|
||||
jsTestLog(
|
||||
`Testing that SnapshotUnavailable during ${op} is labelled TransientTransactionError`);
|
||||
|
||||
session.startTransaction();
|
||||
session.startTransaction({readConcern: {level: "snapshot"}});
|
||||
assert.commandWorked(sessionDB.runCommand({insert: collName, documents: [{}]}));
|
||||
// Create collection outside transaction, cannot write to it in the transaction
|
||||
assert.commandWorked(primaryDB.getSiblingDB(dbNameB).runCommand({create: collNameB}));
|
||||
|
@ -106,7 +106,8 @@ ReadConcernLevel ReadConcernArgs::getLevel() const {
|
||||
}
|
||||
|
||||
ReadConcernLevel ReadConcernArgs::getOriginalLevel() const {
|
||||
return _originalLevel.value_or(getLevel());
|
||||
// If no read concern specified, default to "local"
|
||||
return _originalLevel.value_or(ReadConcernLevel::kLocalReadConcern);
|
||||
}
|
||||
|
||||
bool ReadConcernArgs::hasLevel() const {
|
||||
|
@ -510,6 +510,7 @@ TEST(UpconvertReadConcernLevelToSnapshot, EmptyLevel) {
|
||||
|
||||
ASSERT_OK(readConcern.upconvertReadConcernLevelToSnapshot());
|
||||
ASSERT(ReadConcernLevel::kSnapshotReadConcern == readConcern.getLevel());
|
||||
ASSERT(ReadConcernLevel::kLocalReadConcern == readConcern.getOriginalLevel());
|
||||
}
|
||||
|
||||
TEST(UpconvertReadConcernLevelToSnapshot, LevelLocal) {
|
||||
@ -522,6 +523,7 @@ TEST(UpconvertReadConcernLevelToSnapshot, LevelLocal) {
|
||||
|
||||
ASSERT_OK(readConcern.upconvertReadConcernLevelToSnapshot());
|
||||
ASSERT(ReadConcernLevel::kSnapshotReadConcern == readConcern.getLevel());
|
||||
ASSERT(ReadConcernLevel::kLocalReadConcern == readConcern.getOriginalLevel());
|
||||
}
|
||||
|
||||
TEST(UpconvertReadConcernLevelToSnapshot, LevelMajority) {
|
||||
@ -535,6 +537,7 @@ TEST(UpconvertReadConcernLevelToSnapshot, LevelMajority) {
|
||||
|
||||
ASSERT_OK(readConcern.upconvertReadConcernLevelToSnapshot());
|
||||
ASSERT(ReadConcernLevel::kSnapshotReadConcern == readConcern.getLevel());
|
||||
ASSERT(ReadConcernLevel::kMajorityReadConcern == readConcern.getOriginalLevel());
|
||||
}
|
||||
|
||||
TEST(UpconvertReadConcernLevelToSnapshot, LevelSnapshot) {
|
||||
@ -548,6 +551,7 @@ TEST(UpconvertReadConcernLevelToSnapshot, LevelSnapshot) {
|
||||
|
||||
ASSERT_OK(readConcern.upconvertReadConcernLevelToSnapshot());
|
||||
ASSERT(ReadConcernLevel::kSnapshotReadConcern == readConcern.getLevel());
|
||||
ASSERT(ReadConcernLevel::kSnapshotReadConcern == readConcern.getOriginalLevel());
|
||||
}
|
||||
|
||||
TEST(UpconvertReadConcernLevelToSnapshot, LevelSnapshotWithAtClusterTime) {
|
||||
@ -565,6 +569,7 @@ TEST(UpconvertReadConcernLevelToSnapshot, LevelSnapshotWithAtClusterTime) {
|
||||
|
||||
ASSERT_OK(readConcern.upconvertReadConcernLevelToSnapshot());
|
||||
ASSERT(ReadConcernLevel::kSnapshotReadConcern == readConcern.getLevel());
|
||||
ASSERT(ReadConcernLevel::kSnapshotReadConcern == readConcern.getOriginalLevel());
|
||||
ASSERT_TRUE(readConcern.getArgsAtClusterTime());
|
||||
}
|
||||
|
||||
@ -581,6 +586,7 @@ TEST(UpconvertReadConcernLevelToSnapshot, AfterClusterTime) {
|
||||
|
||||
ASSERT_OK(readConcern.upconvertReadConcernLevelToSnapshot());
|
||||
ASSERT(ReadConcernLevel::kSnapshotReadConcern == readConcern.getLevel());
|
||||
ASSERT(ReadConcernLevel::kLocalReadConcern == readConcern.getOriginalLevel());
|
||||
ASSERT_TRUE(readConcern.getArgsAfterClusterTime());
|
||||
}
|
||||
|
||||
@ -595,6 +601,7 @@ TEST(UpconvertReadConcernLevelToSnapshot, LevelAvailable) {
|
||||
|
||||
ASSERT_NOT_OK(readConcern.upconvertReadConcernLevelToSnapshot());
|
||||
ASSERT(ReadConcernLevel::kAvailableReadConcern == readConcern.getLevel());
|
||||
ASSERT(ReadConcernLevel::kAvailableReadConcern == readConcern.getOriginalLevel());
|
||||
}
|
||||
|
||||
TEST(UpconvertReadConcernLevelToSnapshot, LevelLinearizable) {
|
||||
@ -608,6 +615,7 @@ TEST(UpconvertReadConcernLevelToSnapshot, LevelLinearizable) {
|
||||
|
||||
ASSERT_NOT_OK(readConcern.upconvertReadConcernLevelToSnapshot());
|
||||
ASSERT(ReadConcernLevel::kLinearizableReadConcern == readConcern.getLevel());
|
||||
ASSERT(ReadConcernLevel::kLinearizableReadConcern == readConcern.getOriginalLevel());
|
||||
}
|
||||
|
||||
TEST(UpconvertReadConcernLevelToSnapshot, AfterOpTime) {
|
||||
@ -624,6 +632,7 @@ TEST(UpconvertReadConcernLevelToSnapshot, AfterOpTime) {
|
||||
|
||||
ASSERT_NOT_OK(readConcern.upconvertReadConcernLevelToSnapshot());
|
||||
ASSERT(ReadConcernLevel::kLocalReadConcern == readConcern.getLevel());
|
||||
ASSERT(ReadConcernLevel::kLocalReadConcern == readConcern.getOriginalLevel());
|
||||
ASSERT_TRUE(readConcern.getArgsOpTime());
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user