summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorLingzhi Deng <lingzhi.deng@mongodb.com>2021-02-13 16:25:24 -0500
committerEvergreen Agent <no-reply@evergreen.mongodb.com>2021-02-16 15:05:50 +0000
commit932032e1f3749d25cf17fd477bf9feddf1a2bdeb (patch)
treef33cb44f2183336f691db734ea4174bb0a789953
parentbc90b32880745415b1b6d18cf1971e19c2982c46 (diff)
downloadmongo-932032e1f3749d25cf17fd477bf9feddf1a2bdeb.tar.gz
SERVER-54534: No need to wait for writeConcern on aborting multi-document transactions
-rw-r--r--jstests/noPassthrough/readConcern_snapshot.js3
-rw-r--r--jstests/replsets/transactions_wait_for_write_concern.js14
-rw-r--r--src/mongo/db/service_entry_point_mongod.cpp24
3 files changed, 9 insertions, 32 deletions
diff --git a/jstests/noPassthrough/readConcern_snapshot.js b/jstests/noPassthrough/readConcern_snapshot.js
index d0c2127ac0c..6400c376aff 100644
--- a/jstests/noPassthrough/readConcern_snapshot.js
+++ b/jstests/noPassthrough/readConcern_snapshot.js
@@ -106,8 +106,7 @@ rst = new ReplSetTest({nodes: 1});
rst.startSet();
rst.initiate();
let testDB = rst.getPrimary().getDB(dbName);
-let coll = testDB.coll;
-assert.commandWorked(coll.createIndex({geo: "2d"}));
+assert.commandWorked(testDB.runCommand({create: collName, writeConcern: {w: "majority"}}));
// Test snapshot in a transaction.
session = testDB.getMongo().startSession({causalConsistency: false});
diff --git a/jstests/replsets/transactions_wait_for_write_concern.js b/jstests/replsets/transactions_wait_for_write_concern.js
index 12d1154a28a..28ced9cd37c 100644
--- a/jstests/replsets/transactions_wait_for_write_concern.js
+++ b/jstests/replsets/transactions_wait_for_write_concern.js
@@ -93,16 +93,6 @@ function runTest(readConcernLevel) {
printjson(assert.commandWorked(sessionDB5.runCommand(fruitlessUpdate5)));
let prepareTS5 = PrepareHelpers.prepareTransaction(session5);
- jsTestLog("Unprepared Abort On Used Connection Setup");
- const session6 = primary.getDB("admin").getMongo().startSession();
- const sessionDB6 = session6.getDatabase(dbName);
- session6.startTransaction({
- writeConcern: {w: "majority", wtimeout: failTimeoutMS},
- readConcern: {level: readConcernLevel}
- });
- const fruitlessUpdate6 = {update: collName, updates: [{q: {x: 6}, u: {$set: {x: 6}}}]};
- printjson(assert.commandWorked(sessionDB6.runCommand(fruitlessUpdate6)));
-
jsTestLog("Stop replication");
stopReplicationOnSecondaries(rst);
@@ -142,10 +132,6 @@ function runTest(readConcernLevel) {
assert.commandFailedWithCode(session5.commitTransaction_forTesting(),
ErrorCodes.WriteConcernFailed);
- jsTestLog("Unprepared Abort On Used Connection Test");
- assert.commandFailedWithCode(session6.abortTransaction_forTesting(),
- ErrorCodes.WriteConcernFailed);
-
jsTestLog("Restart replication");
restartReplicationOnSecondaries(rst);
diff --git a/src/mongo/db/service_entry_point_mongod.cpp b/src/mongo/db/service_entry_point_mongod.cpp
index 324885da92c..6cc6546376e 100644
--- a/src/mongo/db/service_entry_point_mongod.cpp
+++ b/src/mongo/db/service_entry_point_mongod.cpp
@@ -127,22 +127,14 @@ public:
}
// Ensures that if we tried to do a write, we wait for write concern, even if that write was
- // a noop.
- //
- // Transactions do not stash their lockers on commit and abort, so after commit and abort,
- // wasGlobalLockTakenForWrite will return whether any statement in the transaction as a
- // whole acquired the global write lock.
- //
- // Speculative majority semantics dictate that "abortTransaction" should not wait for write
- // concern on operations the transaction observed. As a result, "abortTransaction" only ever
- // waits on an oplog entry it wrote (and has already set lastOp to) or previous writes on
- // the same client.
- if (opCtx->lockState()->wasGlobalLockTakenForWrite()) {
- if (invocation->definition()->getName() != "abortTransaction") {
- repl::ReplClientInfo::forClient(opCtx->getClient())
- .setLastOpToSystemLastOpTime(opCtx);
- lastOpAfterRun = repl::ReplClientInfo::forClient(opCtx->getClient()).getLastOp();
- }
+ // a noop. We do not need to update this for multi-document transactions as read-only/noop
+ // transactions will do a noop write at commit time, which should have incremented the
+ // lastOp. And speculative majority semantics dictate that "abortTransaction" should not
+ // wait for write concern on operations the transaction observed.
+ if (opCtx->lockState()->wasGlobalLockTakenForWrite() &&
+ !opCtx->inMultiDocumentTransaction()) {
+ repl::ReplClientInfo::forClient(opCtx->getClient()).setLastOpToSystemLastOpTime(opCtx);
+ lastOpAfterRun = repl::ReplClientInfo::forClient(opCtx->getClient()).getLastOp();
waitForWriteConcernAndAppendStatus();
return;
}