mongodb源代码分析创建db流程分析

mongo/db/catalog/create_collection.cpp中reateCollection构建元数据文档:将集合信息(命名空间、选项、键前缀等)序列化为 BSON 格式,{ ns: "db.conca", ident: "collection-0--8262702921578327518", md: };

_rs->insertRecord将元数据文档插入到Catalog的记录存储(RecordStore)中,写入到系统表_uri:table:_mdb_catalog中。_mdb_catalog存储集合和索引的元数据信息,_mdb_catalog.wt在数据库文件夹下面:

数据库的信息在哪个文件存储呢?

/mongo/db/catalog/create_collection.cpp是创建集合的核心代码,后面重点分析其中获取数据库的代码。

mongo/db/catalog/create_collection.cpp中_createCollection是命令db.createCollection('conca', { })核心方法。AutoGetOrCreateDb autoDb先获取到对应的数据库。

cpp 复制代码
Status _createCollection(OperationContext* opCtx,
                         const NamespaceString& nss,
                         const CollectionOptions& collectionOptions,
                         const BSONObj& idIndex) {
    ...
        AutoGetOrCreateDb autoDb(opCtx, nss.db(), MODE_IX);
        Lock::CollectionLock collLock(opCtx, nss, MODE_X);

       ...
    });
}

/mongo/db/catalog_raii.cpp中AutoGetOrCreateDb代码,_autoDb.getDb()获取数据库,如果没有获取到db,openDb则进行打开对应的数据库。

cpp 复制代码
AutoGetOrCreateDb::AutoGetOrCreateDb(OperationContext* opCtx,
                                     StringData dbName,
                                     LockMode mode,
                                     Date_t deadline)
    : _autoDb(opCtx, dbName, mode, deadline) {
    invariant(mode == MODE_IX || mode == MODE_X);

    _db = _autoDb.getDb();
    if (!_db) {
        auto databaseHolder = DatabaseHolder::get(opCtx);
        _db = databaseHolder->openDb(opCtx, dbName, &_justCreated);
    }

    auto dss = DatabaseShardingState::get(opCtx, dbName);
    auto dssLock = DatabaseShardingState::DSSLock::lockShared(opCtx, dss);
    dss->checkDbVersion(opCtx, dssLock);
}

/mongo/db/catalog/database_holder_impl.cpp中openDb代码:

std::make_unique<DatabaseImpl>(dbname, ++_epoch)创建数据库实现类DatabaseImpl, newDb->init初始化数据库实现类。auto it = _dbs.find(dbname);再次获取是否存在相同名称的数据库,如果存在则返回,如果不存在则设置进去。

cpp 复制代码
Database* DatabaseHolderImpl::openDb(OperationContext* opCtx, StringData ns, bool* justCreated) {
    const StringData dbname = _todb(ns);
    invariant(opCtx->lockState()->isDbLockedForMode(dbname, MODE_IX));

    if (justCreated)
        *justCreated = false;  // Until proven otherwise.

    stdx::unique_lock<SimpleMutex> lk(_m);

    // The following will insert a nullptr for dbname, which will treated the same as a non-
    // existant database by the get method, yet still counts in getNamesWithConflictingCasing.
    if (auto db = _dbs[dbname])
        return db;

    // We've inserted a nullptr entry for dbname: make sure to remove it on unsuccessful exit.
    auto removeDbGuard = makeGuard([this, &lk, dbname] {
        if (!lk.owns_lock())
            lk.lock();
        _dbs.erase(dbname);
    });

    // Check casing in lock to avoid transient duplicates.
    auto duplicates = _getNamesWithConflictingCasing_inlock(dbname);
    uassert(ErrorCodes::DatabaseDifferCase,
            str::stream() << "db already exists with different case already have: ["
                          << *duplicates.cbegin() << "] trying to create [" << dbname.toString()
                          << "]",
            duplicates.empty());

    // Do the catalog lookup and database creation outside of the scoped lock, because these may
    // block.
    lk.unlock();

    if (CollectionCatalog::get(opCtx).getAllCollectionUUIDsFromDb(dbname).empty()) {
        audit::logCreateDatabase(opCtx->getClient(), dbname);
        if (justCreated)
            *justCreated = true;
    }

    auto newDb = std::make_unique<DatabaseImpl>(dbname, ++_epoch);
    newDb->init(opCtx);

    // Finally replace our nullptr entry with the new Database pointer.
    removeDbGuard.dismiss();
    lk.lock();
    auto it = _dbs.find(dbname);
    // Dropping a database requires a MODE_X lock, so the entry in the `_dbs` map cannot disappear.
    invariant(it != _dbs.end());
    if (it->second) {
        // Creating databases only requires a DB lock in MODE_IX. Thus databases can concurrently
        // created. If this thread "lost the race", return the database object that was persisted in
        // the `_dbs` map.
        return it->second;
    }

    it->second = newDb.release();
    invariant(_getNamesWithConflictingCasing_inlock(dbname.toString()).empty());

    return it->second;
}

/mongo/db/catalog/database_impl.cpp中DatabaseImpl::init代码:

cpp 复制代码
void DatabaseImpl::init(OperationContext* const opCtx) const {
    Status status = validateDBName(_name);

    if (!status.isOK()) {
        warning() << "tried to open invalid db: " << _name;
        uasserted(10028, status.toString());
    }

    auto& catalog = CollectionCatalog::get(opCtx);
    for (const auto& uuid : catalog.getAllCollectionUUIDsFromDb(_name)) {
        auto collection = catalog.lookupCollectionByUUID(uuid);
        invariant(collection);
        // If this is called from the repair path, the collection is already initialized.
        if (!collection->isInitialized())
            collection->init(opCtx);
    }

    // At construction time of the viewCatalog, the CollectionCatalog map wasn't initialized yet,
    // so no system.views collection would be found. Now that we're sufficiently initialized, reload
    // the viewCatalog to populate its in-memory state. If there are problems with the catalog
    // contents as might be caused by incorrect mongod versions or similar, they are found right
    // away.
    auto views = ViewCatalog::get(this);
    Status reloadStatus = views->reload(opCtx, ViewCatalogLookupBehavior::kValidateDurableViews);
    if (!reloadStatus.isOK()) {
        warning() << "Unable to parse views: " << redact(reloadStatus)
                  << "; remove any invalid views from the " << _viewsName
                  << " collection to restore server functionality." << startupWarningsLog;
    }
}

DatabaseImpl::init这段代码是 MongoDB 中DatabaseImpl类的init方法实现,主要功能是完成数据库的初始化工作,包括验证数据库名合法性、初始化集合以及加载视图目录等。

相关推荐
一个天蝎座 白勺 程序猿1 小时前
Python驱动Ksycopg2连接和使用Kingbase:国产数据库实战指南
数据库·python·kingbase·金仓数据库
RunningShare1 小时前
SpringBoot + MongoDB全栈实战:从架构原理到AI集成
大数据·spring boot·mongodb·架构·ai编程
高铭杰2 小时前
Postgresql源码(149)SIMD应用与性能测试
数据库·postgresql·sse·simd
来碗原味的小米粥吧2 小时前
sql题目基础50题
linux·数据库·sql
安当加密2 小时前
PostgreSQL透明加密(TDE)技术深度解析:从实现原理到国密合规实践
数据库·postgresql·区块链
云和数据.ChenGuang2 小时前
MongoDB 认证失败(错误码 18)
数据库·mongodb
程序新视界3 小时前
一篇文章详解你不知道的MySQL JSON数据类型
数据库·mysql·json
卷Java3 小时前
用户权限控制功能实现说明
java·服务器·开发语言·数据库·servlet·微信小程序·uni-app
荣光波比5 小时前
MySQL数据库(八)—— MySQL全量+增量备份方案:从脚本开发到连锁餐饮场景落地
运维·数据库·mysql·云计算
qq_3404740210 小时前
3.0 labview使用SQLServer
数据库·sqlserver·labview