gridfs数据损坏需分层定位:先查fs.files和fs.chunks可读性,再据损坏层级选择mongodump跳过坏块或wt工具直解析*.wt文件,严禁误操作扩大损坏。

mongodump 备份失败、mongorestore 报 EOF 错误、fs.chunks 读取卡死——这些现象基本说明 GridFS 底层数据文件已损坏,不能靠 repairDatabase() 修复,必须分层定位、逐级恢复。
确认损坏范围:先查 fs.files 和 fs.chunks 是否可读
直接在 shell 中执行:db.fs.files.countDocuments({})db.fs.chunks.countDocuments({})
如果任一命令报错(如 error reading collection: EOF 或 Failed to parse),说明对应集合的 WiredTiger 文件已损坏。此时不要继续写入或 compact,避免扩大损坏范围。
- 若
fs.files可读但fs.chunks不可读,大概率是 chunk 数据块文件(如collection-*.wt)损坏,元数据还在 - 若两者都不可读,且
_mdb_catalog.wt文件缺失或损坏(启动时报unable to open catalog),则整个数据库元数据层已失效 - 检查
db.adminCommand({listDatabases: 1})能否返回库列表——若连库都列不出,说明_mdb_catalog.wt或WiredTiger.wt根文件损坏
损坏较轻时:用 mongodump + mongorestore 抢救有效数据
仅当 fs.files 和部分 fs.chunks 文档仍可遍历时适用。重点不是“全量备份”,而是“跳过损坏 chunk”抢出能读的文件。
- 加
--forceTableScan参数强制扫描(MongoDB 5.0+):mongodump --host localhost --port 27017 --db your_db --collection fs.files --out /tmp/backup - 对
fs.chunks使用--query过滤已知有效的files_id(从fs.files导出结果中提取):mongodump --query '{"files_id": {"$in": [ObjectId("..."), ...]}}' --collection fs.chunks ... - 恢复时务必用
mongorestore --drop清空目标库再导入,避免残留损坏文档干扰
元数据损坏(_mdb_catalog.wt 丢失):必须用 wt 工具提取原始数据
这是最棘手的情况:mongod 启动失败、mongodump 完全不可用。核心思路是绕过 MongoDB Server,用 WiredTiger 原生工具直接解析 *.wt 文件。
- 下载对应 MongoDB 版本的
wiredtiger源码,编译出wt命令行工具(注意版本严格匹配,否则解析失败) - 定位数据目录下未损坏的
collection-*.wt文件(如collection-123-*.wt对应fs.files,collection-456-*.wt对应fs.chunks) - 用
wt -C -h . -R dump -t collection-123-*.wt > fs_files.dump提取原始 BSON 数据 - 人工解析
.dump文件,过滤出结构完整、filename和length字段非空的文档,再用mongoimport导入新库
恢复后验证:别只看 count,要校验文件完整性
恢复完成后,db.fs.files.countDocuments({}) 和 db.fs.chunks.countDocuments({}) 数值可能看起来正常,但实际 chunk 数据可能错位或截断。
- 对每个文件 ID 执行:
db.fs.chunks.find({files_id: ObjectId("...")}).sort({n: 1}).toArray(),检查n是否连续、无跳跃 - 用
mongofiles get <filename></filename>尝试下载几个关键文件,再用sha256sum对比原始文件哈希(如有备份) - 重点关注
db.fs.chunks.stats().size和db.fs.chunks.stats().storageSize的比值——若后者远大于前者,说明仍有碎片或残留损坏块未清理干净
_mdb_catalog.wt 这种元数据根文件没了。每种情况对应的工具链和操作顺序完全不同,错一步就可能把还能抢救的数据彻底覆盖掉。











