diff options
author | Esha Maharishi <esha.maharishi@mongodb.com> | 2020-05-19 11:25:17 -0400 |
---|---|---|
committer | Evergreen Agent <no-reply@evergreen.mongodb.com> | 2020-05-20 22:25:47 +0000 |
commit | be253e1614bb05dc9a9ace507b263fb4885dcdee (patch) | |
tree | 03a16f6b2aa3a6bd77ec11deace33a8face7c1c4 /jstests/sharding/txn_single_write_shard_failover.js | |
parent | fbf56a4aee8ccb7bff8d3e8c3c32c7849869bb54 (diff) | |
download | mongo-be253e1614bb05dc9a9ace507b263fb4885dcdee.tar.gz |
SERVER-48307 Disable single-write-shard transaction commit optimization
Diffstat (limited to 'jstests/sharding/txn_single_write_shard_failover.js')
-rw-r--r-- | jstests/sharding/txn_single_write_shard_failover.js | 72 |
1 files changed, 72 insertions, 0 deletions
diff --git a/jstests/sharding/txn_single_write_shard_failover.js b/jstests/sharding/txn_single_write_shard_failover.js new file mode 100644 index 00000000000..f21ba4d5f81 --- /dev/null +++ b/jstests/sharding/txn_single_write_shard_failover.js @@ -0,0 +1,72 @@ +/** + * Runs a single-write-shard transaction which commits, but for which the client retries commit and + * a read-only shard fails over before the second commit attempt. + * + * The second commit attempt should still return a commit decision. + * + * This test was written to reproduce the bug in the original single-write-shard transaction commit + * optimization where if a read-only shard failed over before the client sent a second commit + * attempt, the second commit attempt would return NoSuchTransaction with TransientTransactionError, + * causing the client to retry the whole transaction at a higher transaction number and the + * transaction's write to be applied twice. + * + * TODO (SERVER-48341): Remove requires_fcv_46 after backporting SERVER-48307 to 4.4. + * requires_find_command because legacy queries cannot be run in a session. + * @tags: [requires_find_command, requires_fcv_46, uses_transactions, uses_multi_shard_transaction] + */ + +(function() { +'use strict'; + +load("jstests/libs/fail_point_util.js"); + +const db1Name = "db1"; +const coll1Name = "foo"; +const ns1 = db1Name + "." + coll1Name; + +const db2Name = "db2"; +const coll2Name = "bar"; +const ns2 = db2Name + "." + coll2Name; + +const st = new ShardingTest({ + shards: {rs0: {nodes: 2}, rs1: {nodes: 1}}, + config: 1, + other: { + mongosOptions: {verbose: 3}, + } +}); + +jsTest.log("Create two databases on different primary shards."); +// enableSharding creates the databases. +assert.commandWorked(st.s.adminCommand({enableSharding: db1Name})); +assert.commandWorked(st.s.adminCommand({enableSharding: db2Name})); +assert.commandWorked(st.s.adminCommand({movePrimary: db1Name, to: st.shard0.shardName})); +assert.commandWorked(st.s.adminCommand({movePrimary: db2Name, to: st.shard1.shardName})); + +jsTest.log("Insert data on both shards."); +// This ensures all nodes refresh their routing caches. +st.s.getDB(db1Name).getCollection(coll1Name).insert({_id: "dummy"}); +st.s.getDB(db2Name).getCollection(coll2Name).insert({_id: "dummy"}); + +jsTest.log("Run a single-write-shard transaction and commit it."); +const session = st.s.startSession(); +session.startTransaction(); +session.getDatabase(db1Name).getCollection(coll1Name).findOne({_id: "readOperationOnShard0"}); +session.getDatabase(db2Name).getCollection(coll2Name).insert({_id: "writeOperationOnShard1"}); +// Use adminCommand so we can pass writeConcern. +assert.commandWorked(st.s.adminCommand({ + commitTransaction: 1, + lsid: session.getSessionId(), + txnNumber: session.getTxnNumber_forTesting(), + autocommit: false, + writeConcern: {w: "majority"}, +})); + +jsTest.log("Induce a failover on the read shard."); +assert.commandWorked(st.rs0.getPrimary().adminCommand({replSetStepDown: 60, force: true})); + +jsTest.log("Make second attempt to commit, should still return that the transaction committed"); +assert.commandWorked(session.commitTransaction_forTesting()); + +st.stop(); +})(); |