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

    • Type: Icon: Bug Bug
    • Resolution: Fixed
    • Priority: Icon: Major - P3 Major - P3
    • 4.2.2, 4.3.2
    • Affects Version/s: None
    • Component/s: Sharding
    • Labels:
      None
    • Fully Compatible
    • ALL
    • 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(); })();
    • Sharding 2019-11-18

      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.

            Assignee:
            kevin.pulo@mongodb.com Kevin Pulo
            Reporter:
            jack.mulrow@mongodb.com Jack Mulrow
            Votes:
            0 Vote for this issue
            Watchers:
            2 Start watching this issue

              Created:
              Updated:
              Resolved: