MongoDB 源码学习:创建记录和索引(insertDocuments)
简介
之前写了很多 MongoDB 代码结构、如何处理请求、catalog 与 storage 等,接下来会介绍 MongoDB 创建记录经过了哪些步骤。
首先回顾一下上 N 篇MongoDB 源码学习:Mongo 中的 OpRunner,当时提到不同的命令由不同的 OpRunner 执行,而创建记录的命令就由 InsertOpRunner 来处理。
创建记录都做了些什么
InsertOpRunner 会调用 receivedInsert 方法,继而调用 write_ops_exec.cpp 中的 insertDocuments 方法(这里是创建记录的主要入口)
接下来介绍一下,创建记录经过以下步骤:
通过WriteUnitOfWork机制,确保下面的步骤都是一个原子操作。
当 collection 不存在时候进行创建
为每一条记录分配一个 OplogSlot(包含时间戳)用于记录 Oplog 时候保证有序
调用 storage 创建记录
记录索引
写入 Oplog
当 collection 不存在时候进行创建
在创建记录之前,会检查 collection 是否存在,如果不存在就创建,逻辑相对简单下面直接贴源代码,细节可以翻看MongoDB 源码学习:执行创建 Collection 命令。
为每一条记录分配一个 OplogSlot(包含时间戳)用于记录 Oplog 时候保证有序
在数据库系统中,Oplog 是一个很重要的功能。其记录了数据库的变更操作(例如 insert、update、delete),可以用于数据还原、主从复制等。
对于非事务的创建记录操作,会调用 repl::getNextOpTimes,每一个记录生成一个 OplogSlot。伪代码如下
调用 storage 创建记录与记录索引
在上一步分配好了 Oplogslot 之后,CollectionImpl::insertDocuments
,开始写入数据以及记录索引的部分了(本次只讲述大概的流程,细节后面有机会继续分享)。
会经过以下的流程:
获取 SnapshotId,依赖了 WriteUnitOfWork 的机制。在写入操作结束之后,再次获取一次 SnapshotId 进行对比,确保 SnapshotId 没有变化来保证原子操作。
调用 RecordService 的 insertRecords 写入数据。
调用 IndexCategory 的 indexRecords 写入索引。
写入 Oplog
在写入数据和索引完成之后,会触发OpObserverImpl::onInserts
,在这里会完成 Oplog 的写入操作(同样细节在后续章节分享)。
总结
本次介绍了创建记录和索引的主要流程,其中很多串联了之前分享过得内容,例如创建 collection,WriteUnitOfWork 等,但是留了很多的坑,后面的章节会进行填坑。
to be continue
版权声明: 本文为 InfoQ 作者【云里有只猫】的原创文章。
原文链接:【http://xie.infoq.cn/article/97978fddd7b6ccb94aa684caa】。文章转载请联系作者。
评论