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

Capped collections can contain too many documents after replication recovery

    XMLWordPrintable

    Details

    • Type: Bug
    • Status: Closed
    • Priority: Major - P3
    • Resolution: Fixed
    • Affects Version/s: None
    • Fix Version/s: 4.9.0, 4.4.5, 4.2.14, 4.0.25
    • Component/s: None
    • Labels:
      None
    • Backwards Compatibility:
      Fully Compatible
    • Operating System:
      ALL
    • Backport Requested:
      v4.4, v4.2, v4.0
    • Sprint:
      Execution Team 2021-02-08, Execution Team 2021-02-22, Execution Team 2021-03-08
    • Linked BF Score:
      15

      Description

      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();
      })();
      

        Attachments

          Issue Links

            Activity

              People

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

                Dates

                Created:
                Updated:
                Resolved: