diff options
author | Randolph Tan <randolph@mongodb.com> | 2019-09-13 16:05:48 +0000 |
---|---|---|
committer | evergreen <evergreen@mongodb.com> | 2019-09-13 16:05:48 +0000 |
commit | 87d8a588a8f43c580f26f3c3031e507dea6c7e1e (patch) | |
tree | 913f715a57f1e488aa919592a0810cf57e0155c6 /jstests | |
parent | 121aa792f301b5edbfbda44048f5bcbd6de830b3 (diff) | |
download | mongo-87d8a588a8f43c580f26f3c3031e507dea6c7e1e.tar.gz |
SERVER-40258 Relax locking requirements for sharding metadata refresh on shards
(cherry picked from commit 0d07bf5e7a72a5bce3f7d7d681a71d7ecfe7eb8c)
Diffstat (limited to 'jstests')
-rw-r--r-- | jstests/sharding/prepared_txn_metadata_refresh.js | 88 |
1 files changed, 88 insertions, 0 deletions
diff --git a/jstests/sharding/prepared_txn_metadata_refresh.js b/jstests/sharding/prepared_txn_metadata_refresh.js new file mode 100644 index 00000000000..e65e5e1e918 --- /dev/null +++ b/jstests/sharding/prepared_txn_metadata_refresh.js @@ -0,0 +1,88 @@ +/** + * Test to make sure that transactions doesn't block shard version metadata refresh. + * Test relies on the fact that destination shard does not update it's shard version after a + * migration when doNotRefreshRecipientAfterCommit failpoint is ON. + */ + +(function() { +"use strict"; + +load('./jstests/libs/chunk_manipulation_util.js'); + +var staticMongod = MongoRunner.runMongod({}); // For startParallelOps. + +let st = new ShardingTest({shards: 3, other: {shardOptions: {verbose: 1}}}); + +assert.commandWorked(st.s.adminCommand({enableSharding: 'test'})); +st.ensurePrimaryShard('test', st.shard0.shardName); +assert.commandWorked(st.s.adminCommand({shardCollection: 'test.user', key: {x: 1}})); +assert.commandWorked(st.s.adminCommand({split: 'test.user', middle: {x: 0}})); +assert.commandWorked(st.s.adminCommand({split: 'test.user', middle: {x: -100}})); +assert.commandWorked(st.s.adminCommand({split: 'test.user', middle: {x: 100}})); +assert.commandWorked( + st.s.adminCommand({moveChunk: 'test.user', find: {x: 0}, to: st.shard1.shardName})); +assert.commandWorked( + st.s.adminCommand({moveChunk: 'test.user', find: {x: 100}, to: st.shard2.shardName})); + +// Send a normal write to establish the shard versions outside the transaction. +assert.commandWorked(st.s.getDB('test').runCommand({ + insert: 'user', + documents: [{x: 0}, {x: 100}], +})); + +let lsid = {id: UUID()}; +let txnNumber = 0; + +// Start a migration in parallel to get around the X lock acquisition at the beginning of +// migration at the destination. +assert.commandWorked(st.rs0.getPrimary().getDB('admin').runCommand( + {configureFailPoint: 'doNotRefreshRecipientAfterCommit', mode: 'alwaysOn'})); + +let destPrimary = st.rs2.getPrimary(); +pauseMigrateAtStep(destPrimary, migrateStepNames.cloned); +var joinMoveChunk = + moveChunkParallel(staticMongod, st.s0.host, {x: -100}, null, 'test.user', st.shard2.shardName); +waitForMigrateStep(destPrimary, migrateStepNames.cloned); + +assert.commandWorked(st.s.getDB('test').runCommand({ + insert: 'user', + documents: [{x: 1}, {x: 101}], + lsid: lsid, + txnNumber: NumberLong(txnNumber), + stmtId: NumberInt(0), + startTransaction: true, + autocommit: false, +})); + +unpauseMigrateAtStep(destPrimary, migrateStepNames.cloned); +joinMoveChunk(); + +// Make the transaction stay in prepared state so it will hold on to the collection locks. +assert.commandWorked(st.rs1.getPrimary().getDB('admin').runCommand( + {configureFailPoint: 'hangBeforeWritingDecision', mode: 'alwaysOn'})); +assert.commandWorked(st.rs2.getPrimary().getDB('admin').runCommand( + {configureFailPoint: 'hangBeforeWritingDecision', mode: 'alwaysOn'})); + +const runCommitCode = "db.adminCommand({" + + "commitTransaction: 1," + + "lsid: " + tojson(lsid) + "," + + "txnNumber: NumberLong(" + txnNumber + ")," + + "stmtId: NumberInt(0)," + + "autocommit: false," + + "});"; +let commitTxn = startParallelShell(runCommitCode, st.s.port); + +// Insert should be able to refresh the sharding metadata even with existing transactions +// holding the collection lock in IX. +assert.commandWorked( + st.s.getDB('test').runCommand({insert: 'user', documents: [{x: -100}], maxTimeMS: 5 * 1000})); + +assert.commandWorked(st.rs1.getPrimary().getDB('admin').runCommand( + {configureFailPoint: 'hangBeforeWritingDecision', mode: 'off'})); +assert.commandWorked(st.rs2.getPrimary().getDB('admin').runCommand( + {configureFailPoint: 'hangBeforeWritingDecision', mode: 'off'})); +commitTxn(); + +st.stop(); +MongoRunner.stopMongod(staticMongod); +})(); |