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

Capped collections can contain too many documents after replication recovery

    • Type: Icon: Bug Bug
    • Resolution: Fixed
    • Priority: Icon: Major - P3 Major - P3
    • 4.9.0, 4.4.5, 4.2.14, 4.0.25
    • Affects Version/s: None
    • Component/s: None
    • Labels:
      None
    • Fully Compatible
    • ALL
    • v4.4, v4.2, v4.0
    • Execution Team 2021-02-08, Execution Team 2021-02-22, Execution Team 2021-03-08
    • 15

      Starting in SERVER-25025, we mark a collection as always needing size adjustment only if we are in rollback or replication recovery. However, we only set the inReplicationRecovery flag once we are in ReplicationRecoveryImpl::recoverFromOplog, which occurs after the aforementioned check for replication recovery.

      This causes an issue for capped collections when the number of inserts applied during replication recovery is greater than collection's max number of documents. Since we're erroneously not adjusting the count, these documents will not delete other documents already inserted during replication recovery, causing the capped collection to contain more documents than it should until collection validation is run to correct the fast count.

      The following jstest reproduces the issue:

      /**
       * Reproduces the issue described in SERVER-52833.
       */
      (function() {
      "use strict";
      
      load("jstests/libs/fail_point_util.js");
      
      const rst = new ReplSetTest({nodes: 1});
      rst.startSet();
      rst.initiate();
      
      const primary = rst.getPrimary();
      const testDB = primary.getDB("test");
      const coll = testDB.getCollection(jsTestName());
      
      assert.commandWorked(testDB.createCollection(coll.getName(), {capped: true, size: 100, max: 1}));
      
      const ts = assert.commandWorked(testDB.runCommand({insert: coll.getName(), documents: [{a: 1}]}))
                     .operationTime;
      configureFailPoint(primary, "holdStableTimestampAtSpecificTimestamp", {timestamp: ts});
      
      assert.commandWorked(coll.insert([{b: 1}, {b: 2}]));
      rst.restart(primary);
      
      rst.stopSet();
      })();
      

            Assignee:
            gregory.noma@mongodb.com Gregory Noma
            Reporter:
            gregory.noma@mongodb.com Gregory Noma
            Votes:
            0 Vote for this issue
            Watchers:
            4 Start watching this issue

              Created:
              Updated:
              Resolved: