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

Iterating indices in KVCatalog can throw WCE with debug build

    • Type: Icon: Bug Bug
    • Resolution: Done
    • Priority: Icon: Minor - P4 Minor - P4
    • None
    • Affects Version/s: 3.0.0
    • Component/s: Storage
    • Labels:
      None
    • Storage Execution
    • ALL
    • Hide

      The simplest way to reproduce is to compile a debug build (--dbg=on), start up a mongod with --storageEngine=wiredTiger --setParameter enableTestCommands=1, and run the following script:

      db.foo.drop();
      
      var doc = { _id: ObjectId() };
      db.foo.insert(doc);
      assert.eq(doc, db.foo.find({}).limit(1).next());
      
      db.adminCommand({ configureFailPoint: 'WTWriteConflictException', mode: { activationProbability: 0.25 }});
      
      // Write conflict is triggered at least once with high probability
      for (var i = 0; i < 100; ++i) {
          assert.eq(doc, db.foo.find({}).limit(1).next());
      }
      
      Show
      The simplest way to reproduce is to compile a debug build ( --dbg=on ), start up a mongod with --storageEngine=wiredTiger --setParameter enableTestCommands=1 , and run the following script: db.foo.drop(); var doc = { _id: ObjectId() }; db.foo.insert(doc); assert .eq(doc, db.foo.find({}).limit(1).next()); db.adminCommand({ configureFailPoint: 'WTWriteConflictException' , mode: { activationProbability: 0.25 }}); // Write conflict is triggered at least once with high probability for ( var i = 0; i < 100; ++i) { assert .eq(doc, db.foo.find({}).limit(1).next()); }

      The invariant that checks whether an index is ready can trigger a WriteConflictException, which causes the client connection to be closed:

      2015-03-13T00:27:23.699-0400 I NETWORK  DBClientCursor::init call() failed
      2015-03-13T00:27:23.720-0400 E QUERY    Error: error doing query: failed
          at DBQuery._exec (src/mongo/shell/query.js:83:36)
          at DBQuery.next (src/mongo/shell/query.js:249:10)
          at (shell):2:45 at src/mongo/shell/query.js:83
      
      mongo::printStackTrace(std::__1::basic_ostream<char, std::__1::char_traits<char> >&) (in mongod) (stacktrace_posix.cpp:104)
      mongo::WriteConflictException::WriteConflictException() (in mongod) (write_conflict_exception.cpp:50)
      mongo::WriteConflictException::WriteConflictException() (in mongod) (write_conflict_exception.cpp:51)
      mongo::wtRCToStatus_slow(int, char const*) (in mongod) (wiredtiger_util.cpp:59)
      mongo::wtRCToStatus(int, char const*) (in mongod) (wiredtiger_util.h:62)
      mongo::WiredTigerRecordStore::findRecord(mongo::OperationContext*, mongo::RecordId const&, mongo::RecordData*) const (in mongod) (wiredtiger_record_store.cpp:345)
      mongo::KVCatalog::_findEntry(mongo::OperationContext*, mongo::StringData, mongo::RecordId*) const (in mongod) (kv_catalog.cpp:241)
      mongo::KVCatalog::getMetaData(mongo::OperationContext*, mongo::StringData) (in mongod) (kv_catalog.cpp:257)
      mongo::KVCollectionCatalogEntry::_getMetaData(mongo::OperationContext*) const (in mongod) (kv_collection_catalog_entry.cpp:182)
      mongo::BSONCollectionCatalogEntry::isIndexReady(mongo::OperationContext*, mongo::StringData) const (in mongod) (bson_collection_catalog_entry.cpp:102)
      mongo::IndexCatalogEntry::_catalogIsReady(mongo::OperationContext*) const (in mongod) (index_catalog_entry.cpp:220)
      mongo::IndexCatalogEntry::isReady(mongo::OperationContext*) const (in mongod) (index_catalog_entry.cpp:110)
      mongo::IndexCatalog::IndexIterator::_advance() (in mongod) (index_catalog.cpp:937)
      mongo::IndexCatalog::IndexIterator::more() (in mongod) (index_catalog.cpp:911)
      mongo::fillOutPlannerParams(mongo::OperationContext*, mongo::Collection*, mongo::CanonicalQuery*, mongo::QueryPlannerParams*) (in mongod) (get_executor.cpp:122)
      mongo::(anonymous namespace)::prepareExecution(mongo::OperationContext*, mongo::Collection*, mongo::WorkingSet*, mongo::CanonicalQuery*, unsigned long, mongo::PlanStage**, mongo::QuerySolution**) (in mongod) (get_executor.cpp:229)
      mongo::getExecutor(mongo::OperationContext*, mongo::Collection*, mongo::CanonicalQuery*, mongo::PlanExecutor::YieldPolicy, mongo::PlanExecutor**, unsigned long) (in mongod) (get_executor.cpp:420)
      mongo::runQuery(mongo::OperationContext*, mongo::Message&, mongo::QueryMessage&, mongo::NamespaceString const&, mongo::CurOp&, mongo::Message&, bool) (in mongod) (find.cpp:676)
      mongo::receivedQuery(mongo::OperationContext*, mongo::Client&, mongo::DbResponse&, mongo::Message&, bool) (in mongod) (instance.cpp:220)
      mongo::assembleResponse(mongo::OperationContext*, mongo::Message&, mongo::DbResponse&, mongo::HostAndPort const&, bool) (in mongod) (instance.cpp:403)
      mongo::MyMessageHandler::process(mongo::Message&, mongo::AbstractMessagingPort*, mongo::LastError*) (in mongod) (db.cpp:206)
      mongo::PortMessageServer::handleIncomingMsg(void*) (in mongod) (message_server_port.cpp:230)
      boost::detail::thread_data<std::__1::__bind<void* (*)(void*), mongo::(anonymous namespace)::MessagingPortWithHandler*> >::run() (in mongod) (thread.hpp:116)
      boost::(anonymous namespace)::thread_proxy(void*) (in mongod) (thread.cpp:173)
      

            Assignee:
            backlog-server-execution [DO NOT USE] Backlog - Storage Execution Team
            Reporter:
            max.hirschhorn@mongodb.com Max Hirschhorn
            Votes:
            0 Vote for this issue
            Watchers:
            7 Start watching this issue

              Created:
              Updated:
              Resolved: