英文原文:http://www.kchodorow.com/blog/2012/10/04/how-mongodbs-journaling-works/

How MongoDB’s Journaling Works


我在写MongoDB《The Definitive Guide》的“日志内部结构”这一部分。然而我意识到这是大多数人都不关心的一个实现细节。无论怎样,我用简洁的图示来讲解这个过程。

154714853.jpg

Good idea, Patrick!

那么, MongoDB日志是如何工作的呢?

我们用下图表示硬盘上的数据文件日志文件:

153012511.png

当你使用mongod启动MongoDB的时候,数据文件将被加载到共享视图。基本上,操作系统说:“OK,你的数据占用2,000bytes的磁盘空间,我将加载他们到内存地址为1,000,000-1,002,000.所以,如果你读内存地址为1,000,042,你就可以获取这个文件的第42个byte的数据。”(其实,除非你真的存取这些内存地址,否则这些数据没必要加载)

153012530.png

这段内存仍然被这个数据文件占有:如果你在这段内存中做修改,操作系统将刷新这个文件,修改数据。这就是mongod不开启日志的工作方式:进程每60秒通知操作系统对这段内存做flush操作。

然而,启用日志,mongod会建立另一个内存映射用作私有视图。这就是为什么需要分配两倍于mongod所占内存的内存量给日志操作的原因。

153013188.png

需要注意的是私有视图不直接关联到数据文件,所用操作系统不能通过刷新私有视图来写数据到磁盘。

现在,当你有一个写操作,mongod进程就把这个操作写到私有视图。

153013527.png

mongod进程会把这个操作写到日志文件,并描述哪个文件的哪个字节有修改。

153013962.png

日志记录每一个修改操作。

153014653.png

这个时候,写操作是安全的。如果mongod进程崩溃,日志可以重现此次修改,即使还没有对数据文件做更新操作。

153014695.png

然后,mongod进程重新将共享视图映射到私有视图,这样可以防止私有视图过于“dirty”(相对于映射过来的共享视图有太多的修改)。

153014354.png

最后,经过一系列漫长的验证,共享视图数据将会被刷新到磁盘。默认情况下,mongod每60秒对OS请求一次刷新操作。

And that’s how journaling works. Thanks to Richard, who gave the best explanation of this I’ve heard (Richard is going to be teaching an online course on MongoDB this fall, if you’re interested in more wisdom from the source).