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

Concurrent collection drops can return NamespaceNotFound instead of CollectionUUIDMismatch

    XMLWordPrintableJSON

Details

    • Bug
    • Status: Closed
    • Major - P3
    • Resolution: Fixed
    • None
    • 6.0.2, 6.1.0-rc0
    • None
    • None
    • Fully Compatible
    • ALL
    • v6.0
    • Execution Team 2022-08-08, Execution Team 2022-08-22

    Description

      Because the dropCollection command releases and reacquires locks, after reacquiring locks it has to perform some checks again including whether the collection still exists. If there are multiple concurrent commands trying to drop the same collection, one thread can actually do the drop while another has yielded its locks. If the collectionUUID parameter was specified, this should result in a CollectionUUIDMismatch error rather than NamespaceNotFound. The following test reproduces this issue.

      /**
       * Tests that CollectionUUIDMismatch is properly returned with concurrent collection drops.
       */
      (function() {
      'use strict';
       
      load('jstests/libs/parallel_shell_helpers.js');
      load('jstests/libs/wait_for_command.js');
       
      const testDB = db.getSiblingDB(jsTestName());
      testDB.dropDatabase();
       
      const coll = testDB.coll;
      assert.commandWorked(testDB.createCollection(coll.getName()));
       
      const uuid = assert.commandWorked(testDB.runCommand({listCollections: 1}))
                       .cursor.firstBatch.find(c => c.name === coll.getName())
                       .info.uuid;
       
      const sleepCommand = startParallelShell(
          funWithArgs(function(ns) {
              assert.commandFailedWithCode(
                  db.adminCommand(
                      {sleep: 1, secs: 18000, lockTarget: ns, lock: 'iw', $comment: jsTestName()}),
                  ErrorCodes.Interrupted);
          }, coll.getFullName()), testDB.getMongo().port);
      const sleepID =
          waitForCommand('sleepCmd',
                         op => (op['ns'] == 'admin.$cmd' && op['command']['$comment'] == jsTestName()),
                         testDB.getSiblingDB('admin'));
       
      const firstDrop = startParallelShell(
          funWithArgs(function(dbName, collName, uuid) {
              assert.commandWorked(
                  db.getSiblingDB(dbName).runCommand({drop: collName, collectionUUID: uuid}));
          }, testDB.getName(), coll.getName(), uuid), testDB.getMongo().port);
      assert.soon(() => {
          return testDB
                     .currentOp({
                         'command.drop': coll.getName(),
                         'command.collectionUUID': uuid,
                         'locks.Collection': 'W',
                         waitingForLock: true,
                     })
                     .inprog.length === 1;
      });
       
      const secondDrop = startParallelShell(
          funWithArgs(function(dbName, collName, uuid) {
              const res = assert.commandFailedWithCode(
                  db.getSiblingDB(dbName).runCommand({drop: collName, collectionUUID: uuid}),
                  ErrorCodes.CollectionUUIDMismatch);
              assert.eq(res.db, dbName);
              assert.eq(res.collectionUUID, uuid);
              assert.eq(res.expectedCollection, collName);
              assert.eq(res.actualCollection, null);
          }, testDB.getName(), coll.getName(), uuid), testDB.getMongo().port);
      assert.soon(() => {
          return testDB
                     .currentOp({
                         'command.drop': coll.getName(),
                         'command.collectionUUID': uuid,
                         'locks.Collection': 'w',
                         waitingForLock: true,
                     })
                     .inprog.length === 1;
      });
       
      assert.commandWorked(testDB.getSiblingDB('admin').killOp(sleepID));
      sleepCommand();
      firstDrop();
      secondDrop();
      })();
      

      Attachments

        Activity

          People

            fausto.leyva@mongodb.com Fausto Leyva
            gregory.noma@mongodb.com Gregory Noma
            Votes:
            0 Vote for this issue
            Watchers:
            8 Start watching this issue

            Dates

              Created:
              Updated:
              Resolved: