OPTIONS
翻译或纠错本页面

Journaling机制

当MongoDB运行在journaling状态下时, write operations 在写入磁盘数据文件之前会先写入内存和journal文件。本文讨论在MongoDB系统中的journaling机制以及它的实现。更多关于配置、调试和管理journaling的信息请参看 Manage Journaling

Journal文件

当journaling开启后,MongoDB在定义好的 dbPath 路径下创建一个journal子目录,dbPath默认路径为 /data/db 。journal目录用来存放journal文件,该文件用来记录write-ahead redo日志。该目录下还包含一个用来保存最近队列数的文件。一次正常的shutdown会删除journal目录下的所有文件,而非正常的shutdown(比如崩溃)则不会删除文件。当mongod进程重启时,这些文件用来自动恢复数据库保证数据的一致性。

Journal文件是只追加文件,文件名以 j._ 开头。当journal文件达到1G数据时,MongoDB会创建一个新的journal文件。一旦某个journal文件的所有写操作都被刷新到数据库数据文件之后,MongoDB将删除掉这个文件,因为以后都不会再用该文件来进行数据恢复了。除非你每秒进行大量数据的写入,否则journal目录里应该只会有两三个文件。

如果愿意,您可以在 mongod 启动时利用启动参数 storage.smallFiles 限制每个journal的大小为128M。

为了提高当前journal文件频繁的顺序写入速度,您可以将journal文件放在与数据库数据文件不同的文件系统下。

重要

如果将journal文件放在与数据文件不同的文件系统下,那么将 不能 单独使用文件系统快照备份 dbPath 目录下的文件。在这种情况下,利用 fsyncLock() 方法来确保数据库文件的一致性,等快照生成完毕之后使用 fsyncUnlock() 方法释放锁定。

注解

根据你文件系统的不同,当第一次以journaling方式启动一个 mongod 进程时,可能会因为预分配而产生延时。

如果 mongod 进程认为预分配journal文件比在需要时去创建一个新的journal文件更有效,那么MongoDB会预先分配journal文件。预分配所需要的时间可能需要几分钟,在这段时间里是连接不了数据库的。这是一次性预分配,在以后的调用中都不会发生再分配。

为了避免预分配带来的延时,可以参见 Avoid Preallocation Lag

journaling中的存储视图

journaling中包括三种内部存储视图来服务MongoDB

The shared view stores modified data for upload to the MongoDB data files. The shared view is the only view with direct access to the MongoDB data files. When running with journaling, mongod asks the operating system to map your existing on-disk data files to the shared view virtual memory view. The operating system maps the files but does not load them. MongoDB later loads data files into the shared view as needed.

The private view stores data for use with read operations. The private view is the first place MongoDB applies new write operations. Upon a journal commit, MongoDB copies the changes made in the private view to the shared view, where they are then available for uploading to the database data files.

journal是一个硬盘视图,用来存储MongoDB将写操作应用到 private view 之后数据文件之前的写操作。journal文件提供健壮性。如果 mongod 进程在将写操作数据写入数据文件之前崩溃,journal文件可以重新将写操作数据应用到 shared view ,最后再加载到数据文件。

journaling如何记录写操作

MongoDB将写操作批量复制到journal文件,这种方式成为批量提交。 “group commits” 可以降低journaling机制对性能的影响,因为批量提交在提交时阻塞所有的写操作。关于默认的提交时间间隔参见 commitIntervalMs

journaling机制存储的都是原始操作,这样MongoDB可以用它来重现以下操作:

  • 文档的插入/更新

  • 索引的修改

  • 对命名空间文件元数据的更改

  • 创建和删除数据库以及他们关联的数据文件

write operations 发生时,MongoDB将数据写入内存的 private view ,然后批量复制写操作到journal文件。journal文件将这些操作存储到磁盘保证持久性。每条journal都描述了写操作在数据文件里发生改变的具体地址。

然后MongoDB将journal文件里的写操作应用到 shared view 。这时, shared view 将与数据文件中的数据不一致。

在默认的60秒间隔内,MongoDB通过操作系统将 shared view 里的数据刷新到磁盘上。这保证了数据文件里的数据与最新写操作数据是一致的。操作系统可以选择高于60秒的频率刷新 shared view ,特别是当系统的空闲内存较少时。

当MongoDB刷新journal文件的写操作到数据文件时,会记录哪些journal写操作已经被刷新过。一旦journal文件中只包含被刷新过的写操作时,这个文件就不会再起到恢复数据的作用,MongoDB会删除它,或者将其回收用作新的journal文件

作为整个journaling机制的一部分,MongoDB会照常请求操作系统将 shared view 重新映射到 private view ,以节省物理内存。这一次的重新映射,操作系统知道将物理内存页共享在 shared viewprivate view 映射之间。

注解

The interaction between the shared view and the on-disk data files is similar to how MongoDB works without journaling, which is that MongoDB asks the operating system to flush in-memory changes back to the data files every 60 seconds.