Uploaded image for project: 'Core Server'
  1. Core Server
  2. SERVER-44289

Retryable writes that change shard key value and owning shard that include write concern fail with InvalidOptions

    XMLWordPrintable

    Details

    • Type: Bug
    • Status: Closed
    • Priority: Major - P3
    • Resolution: Fixed
    • Affects Version/s: None
    • Fix Version/s: 4.2.2, 4.3.2
    • Component/s: Sharding
    • Labels:
      None
    • Backwards Compatibility:
      Fully Compatible
    • Operating System:
      ALL
    • Steps To Reproduce:
      Hide

      (function() {
      "use strict";
       
      const dbName = "test";
      const collName = "foo";
      const ns = dbName + '.' + collName;
       
      const st = new ShardingTest({shards: 2, config: 1});
       
      assert.commandWorked(st.s.adminCommand({enableSharding: dbName}));
      st.ensurePrimaryShard(dbName, st.shard0.shardName);
      assert.commandWorked(st.s.adminCommand({shardCollection: ns, key: {skey: 1}}));
       
      assert.commandWorked(st.s.adminCommand({split: ns, middle: {skey: 0}}));
      assert.commandWorked(st.s.adminCommand({moveChunk: ns, find: {skey: 0}, to: st.shard1.shardName}));
      assert.commandWorked(st.s.getDB(dbName)[collName].insert({skey: 10}));
       
      const sessionDB = st.s.startSession({retryWrites: true}).getDatabase(dbName);
       
      assert.writeOK(sessionDB[collName].update({skey: 10}, {$set: {skey: -10}}));
      sessionDB[collName].findAndModify({query: {skey: -10}, update: {$set: {skey: 10}}});
       
      // Both operations below fail with InvalidOptions.
      assert.writeOK(sessionDB[collName].update({skey: 10}, {$set: {skey: -10}}, {writeConcern: {w: 1}}));
      sessionDB[collName].findAndModify({query: {skey: -10}, update: {$set: {skey: 10}}, writeConcern: {w: 1}});
       
      st.stop();
      })();
      

      Show
      (function() { "use strict";   const dbName = "test"; const collName = "foo"; const ns = dbName + '.' + collName;   const st = new ShardingTest({shards: 2, config: 1});   assert.commandWorked(st.s.adminCommand({enableSharding: dbName})); st.ensurePrimaryShard(dbName, st.shard0.shardName); assert.commandWorked(st.s.adminCommand({shardCollection: ns, key: {skey: 1}}));   assert.commandWorked(st.s.adminCommand({split: ns, middle: {skey: 0}})); assert.commandWorked(st.s.adminCommand({moveChunk: ns, find: {skey: 0}, to: st.shard1.shardName})); assert.commandWorked(st.s.getDB(dbName)[collName].insert({skey: 10}));   const sessionDB = st.s.startSession({retryWrites: true}).getDatabase(dbName);   assert.writeOK(sessionDB[collName].update({skey: 10}, {$set: {skey: -10}})); sessionDB[collName].findAndModify({query: {skey: -10}, update: {$set: {skey: 10}}});   // Both operations below fail with InvalidOptions. assert.writeOK(sessionDB[collName].update({skey: 10}, {$set: {skey: -10}}, {writeConcern: {w: 1}})); sessionDB[collName].findAndModify({query: {skey: -10}, update: {$set: {skey: 10}}, writeConcern: {w: 1}});   st.stop(); })();
    • Sprint:
      Sharding 2019-11-18

      Description

      When a retryable write would change a document's shard key value and cause that document to move chunks, mongos will internally use a transaction to atomically delete and insert the document with the new value. As part of this, mongos will re-run the original command received from the user in a transaction (e.g. in findAndModify), which will fail if the command included a write concern, because write concern is not allowed in a transaction before commit/abort.

      Instead the write concern should only be applied at the commit/abort of the internal transaction.

        Attachments

          Issue Links

            Activity

              People

              • Votes:
                0 Vote for this issue
                Watchers:
                2 Start watching this issue

                Dates

                • Created:
                  Updated:
                  Resolved: