首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >专栏 >Too many open files报错以及WiredTiger 存储引擎与 MongoDB 的关系及原理详解-以及早期的MMAPv1详解-卓伊凡|阿肯|糖果

Too many open files报错以及WiredTiger 存储引擎与 MongoDB 的关系及原理详解-以及早期的MMAPv1详解-卓伊凡|阿肯|糖果

原创
作者头像
卓伊凡
发布2025-07-24 00:09:23
发布2025-07-24 00:09:23
11200
代码可运行
举报
运行总次数:0
代码可运行

Too many open files报错以及WiredTiger 存储引擎与 MongoDB 的关系及原理详解-以及早期的MMAPv1详解-卓伊凡|阿肯|糖果|贝贝|莉莉

引言

关于最近优雅草卓伊凡发布关于MongoDB的内容是由于我们的甲方上线了一个很老的产品,但是他的用户量极大,并且还有各种人搞事情,不断的来GJ,上线刚开始还能勉强撑着,但是随着用户量急剧上升,包括他们的收入订单各方面,以及请求次数的规模及上升,老古董即便是java +spring +redis 配 cdn 加灵活带宽都抗不住问题,而且上线后出问题后都很复杂,这核心有一点就是数据库,MongoDB 我们的版本是3.4.0 而云数据库也就是腾讯云买900多元一月 基础的云MongoDB数据库都是需要最低4.4版本的,这个可就难了,我们版本太老 ,升级的复杂度不亚于重构,于是在这个环境下我们测试环境已经安排在重构,但是生产环境顶着压力做优化,既然是做优化那么在这么老版本的情况下就有很多挑战,很庆幸在我们技术同事以及技术总监卓伊凡的带领下在7月23日终于得到了突破进展,中途有特别多的问题,由卓伊凡拆分一一记录和学习,让我们对数据的深度理解也非常有帮助,在过程中我们积累了很多知识可以逐步细化消化。

针对报错日志我们逐帧分析:

MongoDB数据库问题,由于我们数据库版本比较低3.4.0版本,造成的问题就是频繁掉线,这次重启好了一段时间 但是又掉线了,我们查看了最新的报错日志内容如下:/data/mongodb/: directory-sync: open: Too many open files 2025-07-23T17:01:35.980+0800 I - [conn30] Assertion: 8:24: Too many open files src/mongo/db/catalog/database.cpp 565 2025-07-23T17:01:36.481+0800 E STORAGE [conn30] WiredTiger error (24) [1753261296:481219][88056:0x7f24579d3640], WT_SESSION.create: /data/mongodb/: directory-sync: open: Too many open files 2025-07-23T17:01:36.481+0800 I - [conn30] Assertion: 8:24: Too many open files src/mongo/db/catalog/database.cpp 565 2025-07-23T17:01:36.481+0800 I COMMAND [conn30] command imRoom.mucmsg_b2dee987bf9246248c72e6179a4186e5 command: insert { insert: “mucmsg_b2dee987bf9246248c72e6179a4186e5”, ordered: true, documents: [ { _id: ObjectId(‘6880a474e4b0152006f03769’), body: “{“content”:”你好!”,”deleteTime”:-1,”fromUserId”:”10001347”,”fromUserName”:”喜悦1413”,”messageId”:”d88f5a9651134c9dbf6bb6d4bf0d6c77”,”timeSend”:1…”, event_type: 1, message: “<message type=”groupchat” to=”b2dee987bf9246248c72e6179a4186e5@muc.im.douqmax.com” xmlns=”jabber:client” from=”10001347@im.douqmax.com/android” id=”d8…”, nickname: “”, public_event: 0, room_jid_id: “b2dee987bf9246248c72e6179a4186e5”, room_jid: “b2dee987bf9246248c72e6179a4186e5@muc.im.douqmax.com”, sender_jid: “10001347@im.douqmax.com”, sender: 10001347, ts: 1753261171961, contentType: 1, messageId: “d88f5a9651134c9dbf6bb6d4bf0d6c77”, timeSend: 1753261171.672, deleteTime: -1, content: “你好!” } ] } ninserted:0 exception: 24: Too many open files code:8 numYields:0 reslen:127 locks:{ Global: { acquireCount: { r: 4, w: 4 } }, Database: { acquireCount: { w: 2, W: 2 }, acquireWaitCount: { W: 1 }, timeAcquiringMicros: { W: 18 } }, Collection: { acquireCount: { w: 2 } } } protocol:op_query 1002ms 2025-07-23T17:01:37.483+0800 E STORAGE [conn30] WiredTiger error (24) [1753261297:483173][88056:0x7f24579d3640], WT_SESSION.create: /data/mongodb/: directory-sync: open: Too many open files 2025-07-23T17:01:37.483+0800 I - [conn30] Assertion: 8:24: Too many open files src/mongo/db/catalog/database.cpp 565 2025-07-23T17:01:37.984+0800 E STORAGE [conn30] WiredTiger error (24) [1753261297:984258][88056:0x7f24579d3640], WT_SESSION.create: /data/mongodb/: directory-sync: open: Too many open files 2025-07-23T17:01:37.984+0800 I - [conn30] Assertion: 8:24: Too many open files src/mongo/db/catalog/database.cpp 565 2025-07-23T17:01:37.984+0800 I COMMAND [conn30] command imRoom.mucmsg_b2dee987bf9246248c72e6179a4186e5 command: insert { insert: “mucmsg_b2dee987bf9246248c72e6179a4186e5”, ordered: true, documents: [ { _id: ObjectId(‘6880a474e4b0152006f03769’), body: “{“content”:”你好!”,”deleteTime”:-1,”fromUserId”:”10001347”,”fromUserName”:”喜悦1413”,”messageId”:”d88f5a9651134c9dbf6bb6d4bf0d6c77”,”timeSend”:1…”, event_type: 1, message: “<message type=”groupchat” to=”b2dee987bf9246248c72e6179a4186e5@muc.im.douqmax.com” xmlns=”jabber:client” from=”10001347@im.douqmax.com/android” id=”d8…”, nickname: “”, public_event: 0, room_jid_id: “b2dee987bf9246248c72e6179a4186e5”, room_jid: “b2dee987bf9246248c72e6179a4186e5@muc.im.douqmax.com”, sender_jid: “10001347@im.douqmax.com”, sender: 10001347, ts: 1753261171961, contentType: 1, messageId: “d88f5a9651134c9dbf6bb6d4bf0d6c77”, timeSend: 1753261171.672, deleteTime: -1, content: “你好!” } ] } ninserted:0 exception: 24: Too many open files code:8 numYields:0 reslen:127 locks:{ Global: { acquireCount: { r: 4, w: 4 } }, Database: { acquireCount: { w: 2, W: 2 } }, Collection: { acquireCount: { w: 2 } } } protocol:op_query 1002ms 2025-07-23T17:01:38.986+0800 E STORAGE [conn30] WiredTiger error (24) [1753261298:986211][88056:0x7f24579d3640], WT_SESSION.create: /data/mongodb/: directory-sync: open: Too many open files 2025-07-23T17:01:38.986+0800 I - [conn30] Assertion: 8:24: Too many open files src/mongo/db/catalog/database.cpp 565 2025-07-23T17:01:39.487+0800 E STORAGE [conn30] WiredTiger error (24) [1753261299:487254][88056:0x7f24579d3640], WT_SESSION.create: /data/mongodb/: directory-sync: open: Too many open files 2025-07-23T17:01:39.487+0800 I - [conn30] Assertion: 8:24: Too many open files src/mongo/db/catalog/database.cpp 565 2025-07-23T17:01:39.487+0800 I COMMAND [conn30] command imRoom.mucmsg_b2dee987bf9246248c72e6179a4186e5 command: insert { insert: “mucmsg_b2dee987bf9246248c72e6179a4186e5”, ordered: true, documents: [ { _id: ObjectId(‘6880a474e4b0152006f03769’), body: “{“content”:”你好!”,”deleteTime”:-1,”fromUserId”:”10001347”,”fromUserName”:”喜悦1413”,”messageId”:”d88f5a9651134c9dbf6bb6d4bf0d6c77”,”timeSend”:1…”, event_type: 1, message: “<message type=”groupchat” to=”b2dee987bf9246248c72e6179a4186e5@muc.im.douqmax.com” xmlns=”jabber:client” from=”10001347@im.douqmax.com/android” id=”d8…”, nickname: “”, public_event: 0, room_jid_id: “b2dee987bf9246248c72e6179a4186e5”, room_jid: “b2dee987bf9246248c72e6179a4186e5@muc.im.douqmax.com”, sender_jid: “10001347@im.douqmax.com”, sender: 10001347, ts: 1753261171961, contentType: 1, messageId: “d88f5a9651134c9dbf6bb6d4bf0d6c77”, timeSend: 1753261171.672, deleteTime: -1, content: “你好!” } ] } ninserted:0 exception: 24: Too many open files code:8 numYields:0 reslen:127 locks:{ Global: { acquireCount: { r: 4, w: 4 } }, Database: { acquireCount: { w: 2, W: 2 } }, Collection: { acquireCount: { w: 2 } } } protocol:op_query 1002ms 2025-07-23T17:01:40.489+0800 E STORAGE [conn30] WiredTiger error (24) [1753261300:489067][88056:0x7f24579d3640], WT_SESSION.create: /data/mongodb/: directory-sync: open: Too many open files 2025-07-23T17:01:40.489+0800 I - [conn30] Assertion: 8:24: Too many open files src/mongo/db/catalog/database.cpp 565 2025-07-23T17:01:40.542+0800 E STORAGE [thread3] WiredTiger error (24) [1753261300:542916][88056:0x7f245ddf8640], file:WiredTiger.wt, WT_SESSION.checkpoint: /data/mongodb/WiredTiger.turtle: handle-open: open: Too many open files 2025-07-23T17:01:40.543+0800 E STORAGE [thread3] WiredTiger error (24) [1753261300:543338][88056:0x7f245ddf8640], checkpoint-server: checkpoint server error: Too many open files 2025-07-23T17:01:40.543+0800 E STORAGE [thread3] WiredTiger error (-31804) [1753261300:543350][88056:0x7f245ddf8640], checkpoint-server: the process must exit and restart: WT_PANIC: WiredTiger library panic 2025-07-23T17:01:40.543+0800 I - [thread3] Fatal Assertion 28558 at src/mongo/db/storage/wiredtiger/wiredtiger_util.cpp 361 2025-07-23T17:01:40.543+0800 I - [thread3]

*aborting after fassert() failure

2025-07-23T17:01:40.547+0800 F - [thread3] Got signal: 6 (Aborted).

0x56363ad50f91 0x56363ad50089 0x56363ad5056d 0x7f246163ebf0 0x7f246168c21c 0x7f246163eb46 0x7f2461628833 0x56363a017219 0x56363aa91d56 0x56363a020f52 0x56363a021046 0x56363a02129e 0x56363b6a4441 0x7f246168a4da 0x7f246170f550 ——- BEGIN BACKTRACE ——- {“backtrace”:[{“b”:”563639818000”,”o”:”1538F91”,”s”:”_ZN5mongo15printStackTraceERSo”},{“b”:”563639818000”,”o”:”1538089”},{“b”:”563639818000”,”o”:”153856D”},{“b”:”7F2461600000”,”o”:”3EBF0”},{“b”:”7F2461600000”,”o”:”8C21C”},{“b”:”7F2461600000”,”o”:”3EB46”,”s”:”raise”},{“b”:”7F2461600000”,”o”:”28833”,”s”:”abort”},{“b”:”563639818000”,”o”:”7FF219”,”s”:”_ZN5mongo32fassertFailedNoTraceWithLocationEiPKcj”},{“b”:”563639818000”,”o”:”1279D56”},{“b”:”563639818000”,”o”:”808F52”,”s”:”wt_eventv”},{“b”:”563639818000”,”o”:”809046”,”s”:”wt_err”},{“b”:”563639818000”,”o”:”80929E”,”s”:”wt_panic”},{“b”:”563639818000”,”o”:”1E8C441”},{“b”:”7F2461600000”,”o”:”8A4DA”},{“b”:”7F2461600000”,”o”:”10F550”}],”processInfo”:{ “mongodbVersion” : “3.4.0”, “gitVersion” : “f4240c60f005be757399042dc12f6addbc3170c1”, “compiledModules” : [], “uname” : { “sysname” : “Linux”, “release” : “5.14.0-592.el9.x86_64”, “version” : “#1 SMP PREEMPT_DYNAMIC Fri Jun 6 09:58:38 UTC 2025”, “machine” : “x86_64” }, “somap” : [ { “b” : “563639818000”, “elfType” : 3, “buildId” : “5B66BE773E8A3DF1ACFD66DDAB81BAD0EFDFD034” }, { “b” : “7FFCC639D000”, “path” : “linux-vdso.so.1”, “elfType” : 3, “buildId” : “8F8D1CDBCEB40C33818EB4EDCB146CC4BD747B56” }, { “b” : “7F2461A94000”, “path” : “/lib64/librt.so.1”, “elfType” : 3, “buildId” : “B550D3219FDFFB597677AEBF24771ECA7DA44B73” }, { “b” : “7F2461A8F000”, “path” : “/lib64/libdl.so.2”, “elfType” : 3, “buildId” : “BF9319C7F844A91561BA99B05C4D645EB5961DAF” }, { “b” : “7F24619B4000”, “path” : “/lib64/libm.so.6”, “elfType” : 3, “buildId” : “1A0FBA11391645004B094610CAAAF20645F2F34B” }, { “b” : “7F246199A000”, “path” : “/lib64/libgcc_s.so.1”, “elfType” : 3, “buildId” : “9E6B1FD314A1A84B064878566B3809850E4E53CE” }, { “b” : “7F2461995000”, “path” : “/lib64/libpthread.so.0”, “elfType” : 3, “buildId” : “39F32E6A1DE7344E65F29C40A9BC350192518464” }, { “b” : “7F2461600000”, “path” : “/lib64/libc.so.6”, “elfType” : 3, “buildId” : “5800F569D0B1B2271E710F2B0ED99B76A103389C” }, { “b” : “7F2461AA2000”, “path” : “/lib64/ld-linux-x86-64.so.2”, “elfType” : 3, “buildId” : “7828876F5A27CF4F528E96745F1D954DD1097662” } ] }} mongod(_ZN5mongo15printStackTraceERSo+0x41) [0x56363ad50f91] mongod(+0x1538089) [0x56363ad50089] mongod(+0x153856D) [0x56363ad5056d] libc.so.6(+0x3EBF0) [0x7f246163ebf0] libc.so.6(+0x8C21C) [0x7f246168c21c] libc.so.6(raise+0x16) [0x7f246163eb46] libc.so.6(abort+0xD3) [0x7f2461628833] mongod(_ZN5mongo32fassertFailedNoTraceWithLocationEiPKcj+0x0) [0x56363a017219] mongod(+0x1279D56) [0x56363aa91d56] mongod(wt_eventv+0x422) [0x56363a020f52] mongod(wt_err+0x9D) [0x56363a021046] mongod(wt_panic+0x24) [0x56363a02129e] mongod(+0x1E8C441) [0x56363b6a4441] libc.so.6(+0x8A4DA) [0x7f246168a4da] libc.so.6(+0x10F550) [0x7f246170f550] ——- END BACKTRACE ——-

WiredTiger 存储引擎与 MongoDB 的关系及原理详解

1. 关系概述

WiredTiger 是 MongoDB 的一个存储引擎(Storage Engine),负责管理数据如何存储在磁盘上、如何处理读写操作、事务、压缩等底层细节。MongoDB 自 3.2 版本起将 WiredTiger 作为默认存储引擎,取代了早期的 MMAPv1。

  • 类比: 如果将 MongoDB 比作一辆汽车,存储引擎就是它的发动机。WiredTiger 是一种高性能的“发动机”,支持更先进的特性(如压缩、并发控制),而 MMAPv1 是较老的“发动机”,功能简单但效率较低。
2. WiredTiger 的核心原理
(1) 数据结构
  • B+树索引:默认使用 B+ 树存储数据和索引,优化磁盘访问效率。
  • MVCC(多版本并发控制):通过维护数据的多个版本实现读写并发,写操作不会阻塞读操作。
  • 文档级锁:比 MMAPv1 的集合级锁更细粒度,提高并发性能。
(2) 内存管理
  • 缓存分层:数据按需从磁盘加载到缓存(默认占用 50% 的可用内存),通过 LRU 算法管理。
  • 检查点(Checkpoint):定期将内存中的脏页(修改过的数据)刷到磁盘,默认 60 秒一次,减少崩溃恢复时间。
(3) 压缩
  • 支持 Snappy(默认)和 Zlib 压缩算法,减少磁盘占用(但增加 CPU 开销)。
(4) 日志(Journal)
  • 预写日志(WiredTiger’s redo log)确保数据持久性,崩溃后可通过日志恢复。
3. 文件描述符(File Descriptor)问题

在 MongoDB 3.4.0 中,WiredTiger 对文件描述符的需求较高,可能导致以下问题:

(1) 根本原因
  • WiredTiger 为每个集合和索引创建单独的文件,同时维护多个数据文件、日志文件和临时文件。
  • 高并发或大量集合/索引时,文件描述符可能耗尽(Linux 默认限制为 1024/进程)。
(2) 典型问题
  • “Too many open files”错误:导致 MongoDB 崩溃或无法响应。
  • 性能下降:频繁打开/关闭文件增加延迟。
  • 连接失败:无法创建新的连接或会话。
(3) 解决方案
  • 调整系统限制
代码语言:javascript
代码运行次数:0
运行
复制
ulimit -n 65536  # 临时生效
# 永久生效:修改 /etc/security/limits.conf
  • 优化 MongoDB 配置
代码语言:javascript
代码运行次数:0
运行
复制
storage:
  wiredTiger:
    engineConfig:
      maxCacheOverflowFileSizeGB: 2  # 限制临时文件大小
      cacheSizeGB: 4                # 合理设置缓存大小
  • 减少集合/索引数量:避免过度分片或冗余索引。
  • 监控文件描述符使用
代码语言:javascript
代码运行次数:0
运行
复制
lsof -p <mongod_pid> | wc -l
4. 比喻解释
  • 文件描述符不足: 想象 WiredTiger 是一个图书馆管理员,每个文件描述符是他的一只手。如果图书馆(数据库)有 10,000 本书(文件),但他只有 100 只手(描述符),每次只能同时处理少量书籍,其他请求必须排队,导致效率极低甚至崩溃。
5. 后续版本改进

MongoDB 后续版本(如 4.0+)优化了 WiredTiger 的文件管理:

  • 更高效的文件句柄复用。
  • 动态调整缓存策略。
  • 日志合并减少文件数量。

总结

WiredTiger 是 MongoDB 的高性能存储引擎,但其对文件描述符的高需求在 3.4.0 版本中可能引发稳定性问题。通过系统调优和合理配置可缓解此问题,后续版本已逐步改进。

还记得我们注释mmapv1吧,那么是最早第一次解决报错的提示 当时是说重复启动了服务

MMAPv1 存储引擎详解

MMAPv1 是 MongoDB 在 3.2 版本之前的默认存储引擎,从 MongoDB 4.0 版本开始被完全移除。它是 MongoDB 最早的存储引擎设计,基于内存映射文件(memory-mapped files)技术实现。

核心工作原理

  1. 内存映射文件技术
    • 将数据库文件直接映射到操作系统的虚拟内存中
    • 操作系统负责将文件内容分页(pages)调入调出内存
    • 读写操作直接作用于内存中的映射区域,由OS负责同步到磁盘
  2. 存储结构
    • 每个数据库对应一个独立的.ns文件(命名空间文件)和多个数据文件
    • 数据文件以database.0database.1等形式命名,默认64MB大小,自动增长
    • 使用双向链表结构组织记录(文档)

主要特点

  1. 存储模型
    • 记录分配:使用动态分配策略,文档可以原地更新(当空间足够时)或移动到新位置
    • 空间重用:维护空闲列表(free list)来回收已删除文档的空间
    • 预分配:预先分配数据文件以避免运行时分配延迟
  2. 并发控制
    • 数据库级锁:整个数据库实例使用一个全局读写锁
    • 读操作可以并发,但写操作会阻塞所有其他操作
    • 在3.0版本引入了集合级锁的改进
  3. 数据文件增长
    • 使用指数增长策略(64MB, 128MB, 256MB等)
    • 避免频繁分配小文件带来的性能开销

与WiredTiger的对比

特性

MMAPv1

WiredTiger

存储效率

较低(有碎片)

较高(压缩存储)

并发控制

数据库/集合级锁

文档级锁

内存使用

依赖OS页面管理

自带缓存管理

压缩支持

支持多种压缩算法

事务支持

支持多文档事务(4.0+)

检查点

依赖OS同步

定期检查点

崩溃恢复

依赖journal日志

检查点+journal双重保障

典型使用场景

  1. 适合场景
    • 大量原地更新的工作负载
    • 读密集型应用
    • 不需要压缩的简单部署
  2. 不适合场景
    • 高并发写入环境
    • 需要压缩节省空间的场景
    • 需要事务支持的应用程序

性能特点

  1. 写入性能
    • 小文档的插入性能较好
    • 大文档或需要移动的更新操作性能较差
    • 随着数据增长可能出现碎片问题
  2. 读取性能
    • 热数据(在内存中)读取非常快
    • 冷数据读取依赖OS页面调度
  3. 空间效率
    • 容易产生存储碎片
    • 需要定期运行compact命令或repairDatabase来回收空间

配置参数示例

在MongoDB 3.2之前,可以在配置文件中调整MMAPv1参数:

代码语言:javascript
代码运行次数:0
运行
复制
storage:
  mmapv1:
    smallFiles: true       # 使用较小的数据文件大小(16MB)
    journal:
      enabled: true       # 启用journal日志
    preallocDataFiles: false # 禁用文件预分配

淘汰原因

  1. 锁粒度粗:影响并发性能
  2. 缺乏压缩:存储效率低
  3. 碎片问题:需要额外维护
  4. 功能限制:无法支持现代数据库需求如事务

MMAPv1的设计反映了早期MongoDB对简单性和快速开发的重视,但随着数据库的发展,更先进的WiredTiger引擎成为了更好的选择。

注释这个服务解决了以后,过了仅仅维持了 20分钟我们遇到了新的报错,下文讲

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • Too many open files报错以及WiredTiger 存储引擎与 MongoDB 的关系及原理详解-以及早期的MMAPv1详解-卓伊凡|阿肯|糖果|贝贝|莉莉
  • 引言
    • WiredTiger 存储引擎与 MongoDB 的关系及原理详解
    • 总结
  • MMAPv1 存储引擎详解
    • 核心工作原理
    • 主要特点
    • 与WiredTiger的对比
    • 典型使用场景
    • 性能特点
    • 配置参数示例
    • 淘汰原因
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档