从 MongoDB 3.2 开始,WiredTiger 存储引擎是默认存储引擎。对于现有部署,如果不指定 --storageEngine 或 storage.engine 设置,3.2+版本的 mongod实例可以自动确定用于在 --dbpath 或 storage.dbPath 中创建数据文件的存储引擎。

文档级并发

WiredTiger 使用文档级并发控制进行写入操作。因此,多个客户端可以同时修改一个集合的不同文档。

对于大多数读写操作,WiredTiger 使用乐观并发控制。WiredTiger 仅在全局、数据库和集合级别使用意图锁。当存储引擎检测到两个操作之间的冲突时,会引发写入冲突,导致 MongoDB 透明地重试该操作。

一些全局操作,通常是涉及多个数据库的短期操作,仍然需要全局“实例范围”锁。其他一些操作,例如collMod,仍然需要独占数据库锁。

快照和检查点

WiredTiger 使用多版本并发控制 (MVCC)。在操作开始时,WiredTiger 会为操作提供数据的时间点快照。快照呈现内存中数据的一致视图。

写入磁盘时,WiredTiger 将快照中的所有数据以一致的方式跨所有数据文件写入磁盘。现在持久的 数据充当数据文件中的检查点。检查点确保数据文件在最后一个检查点之前是一致的,包括最后一个检查点;即检查点可以充当恢复点。

从版本 3.6 开始,MongoDB 配置 WiredTiger 以每隔 60 秒创建检查点(即将快照数据写入磁盘)。在早期版本中,MongoDB 将检查点设置为在 WiredTiger 中以 60 秒的间隔或在写入 2 GB 的日志数据时发生在用户数据上,以先发生者为准。

在写入新的检查点期间,之前的检查点仍然有效。因此,即使 MongoDB 在写入新检查点时终止或遇到错误,在重新启动时,MongoDB 也可以从最后一个有效检查点恢复。

当 WiredTiger 的元数据表被原子更新以引用新的检查点时,新的检查点变得可访问和永久。一旦可以访问新的检查点,WiredTiger 就会从旧的检查点中释放页面。

使用 WiredTiger,即使没有日志,MongoDB 也可以从上一个检查点恢复;但是,要恢复在最后一个检查点之后所做的更改,请使用journaling运行。

从 MongoDB 4.0 开始,您不能为使用 WiredTiger 存储引擎的副本集成员指定–nojournal选项或storage.journal.enabled: false。

Journal

WiredTiger 使用预写日志(即日志)结合 检查点来确保数据的持久性。

WiredTiger 日志保留检查点之间的所有数据修改。如果 MongoDB 在检查点之间退出,它会使用日志重放自上一个检查点以来修改的所有数据。有关 MongoDB 将日志数据写入磁盘的频率的信息,请参阅Journaling Process。

WiredTiger 日志使用 snappy压缩库进行压缩。要指定不同的压缩算法或不压缩,请使用该 storage.wiredTiger.engineConfig.journalCompressor设置。有关更改日志压缩器的详细信息,请参阅 更改 WiredTiger 日志压缩器。

如果日志记录小于或等于 128 字节( WiredTiger 的最小日志记录大小),WiredTiger 不会压缩该记录。

您可以通过设置 storage.journal.enabled = false 为来禁用独立实例的日志 ,这可以减少维护日志的开销。对于独立实例,不使用日志意味着,当 MongoDB 意外退出时,您将丢失最后一个检查点之后的所有数据修改。

从 MongoDB 4.0 开始,您不能为使用 WiredTiger 存储引擎的副本集成员指定--nojournal选项或storage.journal.enabled: false

压缩

使用 WiredTiger,MongoDB 支持所有集合和索引的压缩。压缩以增加 CPU 为代价最大限度地减少了存储使用。

默认情况下,WiredTiger 使用 snappy 压缩库对所有集合使用块压缩,对 所有索引使用前缀压缩 。

对于集合,还可以使用以下块压缩库:

  • zlib
  • zstd(从 MongoDB 4.2 开始可用)

要指定替代压缩算法或不压缩,请使用该storage.wiredTiger.collectionConfig.blockCompressor 设置。

对于索引,要禁用前缀压缩,请使用该 storage.wiredTiger.indexConfig.prefixCompression设置。

在收集和索引创建期间,压缩设置也可以在每个集合和每个索引的基础上进行配置。请参阅 指定存储引擎选项和 db.collection.createIndex() storageEngine 选项。

对于大多数工作负载,默认压缩设置会平衡存储效率和处理要求。

WiredTiger 日志也是默认压缩的。有关日记压缩的信息,请参阅日记。

内存使用

借助 WiredTiger,MongoDB 同时利用了 WiredTiger 内部缓存和文件系统缓存。

从 MongoDB 3.4 开始,默认的 WiredTiger 内部缓存大小是以下两者中的较大者:

  • 50% of (RAM - 1 GB), or
  • 256 MB.

例如,在一个总共有 4GB RAM 的系统上,WiredTiger 缓存将使用 1.5GB 的 RAM ( 0.5 * (4 GB - 1 GB) = 1.5 GB)。相反,总共有 1.25 GB RAM 的系统将分配 256 MB 给 WiredTiger 缓存,因为这是总 RAM 减去 1 GB ( 0.5 * (1.25 GB - 1 GB) = 128 MB < 256 MB) 的一半以上。

在某些情况下,例如在容器中运行时,数据库的内存限制可能低于系统总内存。在这种情况下,这个内存限制,而不是总系统内存,被用作最大可用 RAM。

默认情况下,WiredTiger 对所有集合使用 Snappy 块压缩,对所有索引使用前缀压缩。压缩默认值可在全局级别配置,也可以在集合和索引创建期间基于每个集合和每个索引进行设置。

WiredTiger 内部缓存与磁盘格式中的数据使用不同的表示形式:

  • 文件系统缓存中的数据与磁盘格式相同,包括对数据文件进行任何压缩的好处。操作系统使用文件系统缓存来减少磁盘 I/O。
  • 在 WiredTiger 内部缓存中加载的索引与磁盘格式的数据表示不同,但仍可以利用索引前缀压缩来减少 RAM 使用。索引前缀压缩从索引字段中删除了公共前缀的重复数据。
  • WiredTiger 内部缓存中的集合数据未压缩,并使用与磁盘格式不同的表示。块压缩可以显着节省磁盘存储空间,但必须解压缩数据才能被服务器处理。

通过文件系统缓存,MongoDB 自动使用 WiredTiger 缓存或其他进程未使用的所有空闲内存。

要调整 WiredTiger 内部缓存的大小,请参阅 storage.wiredTiger.engineConfig.cacheSizeGB和 --wiredTigerCacheSizeGB。避免将 WiredTiger 内部缓存大小增加到其默认值以上。