diff options
author | Esha Maharishi <esha.maharishi@mongodb.com> | 2019-03-20 10:13:53 -0400 |
---|---|---|
committer | Esha Maharishi <esha.maharishi@mongodb.com> | 2019-03-20 20:34:38 -0400 |
commit | 9614d52c9e83afdde0ae22e16de97f290a08c206 (patch) | |
tree | 646aef5f03ef11ec7f22148c4719e2a4766f725b | |
parent | 40f54965f90cfa986a6b6aa0e693c53464f0bc80 (diff) | |
download | mongo-9614d52c9e83afdde0ae22e16de97f290a08c206.tar.gz |
SERVER-38876 Ensure secondary user operations cannot abort transactions being applied from the oplog
-rw-r--r-- | jstests/replsets/transactions_on_secondaries_not_allowed.js | 25 | ||||
-rw-r--r-- | src/mongo/db/command_can_run_here.cpp | 3 |
2 files changed, 24 insertions, 4 deletions
diff --git a/jstests/replsets/transactions_on_secondaries_not_allowed.js b/jstests/replsets/transactions_on_secondaries_not_allowed.js index d857cef6717..c1e5c332f15 100644 --- a/jstests/replsets/transactions_on_secondaries_not_allowed.js +++ b/jstests/replsets/transactions_on_secondaries_not_allowed.js @@ -11,7 +11,7 @@ const collName = "transactions_on_secondaries_not_allowed"; const rst = new ReplSetTest({name: collName, nodes: 2}); - rst.startSet(); + rst.startSet({verbose: 3}); // We want a stable topology, so make the secondary unelectable. let config = rst.getReplSetConfig(); config.members[1].priority = 0; @@ -26,8 +26,13 @@ assert.commandWorked(primary.getDB(dbName)[collName].insert(initialDoc)); rst.awaitLastOpCommitted(); + // Disable the best-effort check for primary-ness in the service entry point, so that we + // exercise the real check for primary-ness in TransactionParticipant::beginOrContinue. + assert.commandWorked(secondary.adminCommand( + {configureFailPoint: "skipCheckingForNotMasterInCommandDispatch", mode: "alwaysOn"})); + // Initiate a session on the secondary. - const sessionOptions = {causalConsistency: false}; + const sessionOptions = {causalConsistency: false, retryWrites: true}; const session = secondaryTestDB.getMongo().startSession(sessionOptions); const sessionDb = session.getDatabase(dbName); @@ -60,6 +65,22 @@ jsTestLog("Make sure we are not allowed to run the abortTransaction command on the secondary."); assert.commandFailedWithCode(session.abortTransaction_forTesting(), ErrorCodes.NotMaster); + /** + * Test starting a retryable write. + */ + + jsTestLog("Start a retryable write"); + assert.commandFailedWithCode(sessionDb.foo.insert({_id: 0}), ErrorCodes.NotMaster); + + /** + * Test starting a read with txnNumber, but without autocommit. This is not an officially + * supported combination, but should still be disallowed on a secondary. + */ + + jsTestLog("Start a read with txnNumber but without autocommit"); + assert.commandFailedWithCode(sessionDb.runCommand({find: 'foo', txnNumber: NumberLong(10)}), + ErrorCodes.NotMaster); + session.endSession(); rst.stopSet(undefined, false, {skipValidation: true}); }()); diff --git a/src/mongo/db/command_can_run_here.cpp b/src/mongo/db/command_can_run_here.cpp index 17dc5b7b627..37089aefa68 100644 --- a/src/mongo/db/command_can_run_here.cpp +++ b/src/mongo/db/command_can_run_here.cpp @@ -32,7 +32,6 @@ #include "mongo/db/command_can_run_here.h" #include "mongo/client/read_preference.h" -#include "mongo/db/commands/test_commands_enabled.h" #include "mongo/db/repl/replication_coordinator.h" #include "mongo/util/assert_util.h" @@ -47,7 +46,7 @@ bool commandCanRunHere(OperationContext* opCtx, return true; // primary: always ok if (!opCtx->writesAreReplicated()) return true; // standalone: always ok - if (inMultiDocumentTransaction && !getTestCommandsEnabled()) + if (inMultiDocumentTransaction) return false; // Transactions are not allowed on secondaries. switch (command->secondaryAllowed(opCtx->getServiceContext())) { case Command::AllowedOnSecondary::kAlways: |