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

Operations with a CollectionCatalog instance can observe uncommitted collections become committed from a different operation operating on a different CollectionCatalog instance

    • Type: Icon: Bug Bug
    • Resolution: Fixed
    • Priority: Icon: Major - P3 Major - P3
    • 7.1.0-rc0
    • Affects Version/s: None
    • Component/s: None
    • None
    • Fully Compatible
    • ALL
    • Execution Team 2023-05-29, Execution Team 2023-06-12
    • 156

      SERVER-75497 exposed this bug in the CollectionCatalog. In dbHash we started using range(dbName) to hash all collections. There was a BF where we had test.a -> test.b -> test.c but unexpectedly we also tried to hash test_test.d which is when the assertion fired.

      This can be reproduced with SERVER-75497 using the following

      TEST_F(CollectionCatalogTimestampTest, TestIterator) {
          createCollection(opCtx.get(), NamespaceString("test.1"), Timestamp::min());
          createCollection(opCtx.get(), NamespaceString("test.2"), Timestamp::min());
      
          WriteUnitOfWork wuow(opCtx.get());
          _createCollection(opCtx.get(), {NamespaceString("test_test.3")});
          opCtx->recoveryUnit()->runPreCommitHooks(opCtx.get());
      
          auto newClient = opCtx->getServiceContext()->makeClient("AlternativeClient");
          AlternativeClientRegion acr(newClient);
          auto newOpCtx = cc().makeOperationContext();
      
          auto latest = CollectionCatalog::latest(newOpCtx.get());
          auto range = latest->range(NamespaceString("test.1").dbName());
          auto end1 = range.end();
          wuow.commit();
          auto end2 = range.end();
      
          ASSERT(end1 == end2);
      }
      

      In GDB I observed that after the wuow.commit(), _cachedCommitted stays false, but _shared->_committed flips to true in the shared state of the collection.

      I don't think _shared->_committed should be shared. In the example above we're thinking about crossing database boundaries through end(). But we can also have something like test.a -> test.b (uncommitted) -> test.c
      In Op1: we start iterating, and we're on test.a
      In Op2: Commit the WUOW creating test.b
      In Op1: we move on to test.b because it's committed.

            Assignee:
            henrik.edin@mongodb.com Henrik Edin
            Reporter:
            gregory.wlodarek@mongodb.com Gregory Wlodarek
            Votes:
            0 Vote for this issue
            Watchers:
            6 Start watching this issue

              Created:
              Updated:
              Resolved: