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

renameCollection should only generate one oplog entry

    • Type: Icon: Bug Bug
    • Resolution: Done
    • Priority: Icon: Major - P3 Major - P3
    • 3.5.7
    • Affects Version/s: None
    • Component/s: Storage
    • None
    • Fully Compatible
    • ALL
    • Hide

      Run the following test:

      (function(){
          let rs = new ReplSetTest({nodes:1});
          rs.startSet();
          rs.initiate();
      
          let prim = rs.getPrimary();
          let test = prim.getDB("test");
          let local = prim.getDB("local");
      
          test.x.drop();
          test.x.insert({});
          test.y.insert({});
          let ts = local.oplog.rs.find().sort({$natural:-1}).limit(1).next().ts;
          test.y.renameCollection("x", true);
      
          ops = local.oplog.rs.find({ts:{$gt: ts}}).sort({$natural:1}).toArray();
          assert.eq(ops.length, 1,
              "renameCollection was supposed to only generate a single oplog entry: " + tojson(ops));
      })();
      

      Current output is:

      assert: [2] != [1] are not equal : renameCollection was supposed to only generate a single oplog entry: [
      	{
      		"ts" : Timestamp(1489385287, 6),
      		"t" : NumberLong(1),
      		"h" : NumberLong("-3656781107160762734"),
      		"v" : 2,
      		"op" : "c",
      		"ns" : "test.$cmd",
      		"o" : {
      			"drop" : "x"
      		}
      	},
      	{
      		"ts" : Timestamp(1489385287, 7),
      		"t" : NumberLong(1),
      		"h" : NumberLong("-5606475750286919212"),
      		"v" : 2,
      		"op" : "c",
      		"ns" : "test.$cmd",
      		"o" : {
      			"renameCollection" : "test.y",
      			"to" : "test.x",
      			"stayTemp" : false,
      			"dropTarget" : true
      		}
      	}
      ]
      
      Show
      Run the following test: ( function (){ let rs = new ReplSetTest({nodes:1}); rs.startSet(); rs.initiate(); let prim = rs.getPrimary(); let test = prim.getDB( "test" ); let local = prim.getDB( "local" ); test.x.drop(); test.x.insert({}); test.y.insert({}); let ts = local.oplog.rs.find().sort({$natural:-1}).limit(1).next().ts; test.y.renameCollection( "x" , true ); ops = local.oplog.rs.find({ts:{$gt: ts}}).sort({$natural:1}).toArray(); assert.eq(ops.length, 1, "renameCollection was supposed to only generate a single oplog entry: " + tojson(ops)); })(); Current output is: assert: [2] != [1] are not equal : renameCollection was supposed to only generate a single oplog entry: [ { "ts" : Timestamp(1489385287, 6), "t" : NumberLong(1), "h" : NumberLong( "-3656781107160762734" ), "v" : 2, "op" : "c" , "ns" : "test.$cmd" , "o" : { "drop" : "x" } }, { "ts" : Timestamp(1489385287, 7), "t" : NumberLong(1), "h" : NumberLong( "-5606475750286919212" ), "v" : 2, "op" : "c" , "ns" : "test.$cmd" , "o" : { "renameCollection" : "test.y" , "to" : "test.x" , "stayTemp" : false , "dropTarget" : true } } ]
    • Storage 2017-05-08

      With dropTarget : True, the renameCollection command will generate two oplog entries.

      One use of renameCollection is to atomically replace a collection x with an updated version of that collection. However, a read on a secondary could fail to see any version of x at all. Similarly, a crash at that point in time on the primary could result in the secondary taking over without a collection x present. Instead, we should not write the oplog entry for the implicit dropCollection.

            Assignee:
            geert.bosch@mongodb.com Geert Bosch
            Reporter:
            geert.bosch@mongodb.com Geert Bosch
            Votes:
            1 Vote for this issue
            Watchers:
            4 Start watching this issue

              Created:
              Updated:
              Resolved: