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实际下载几个关键文件,再结合sha256sum对比原始文件哈希值(如果有备份) - 重点观察
db.fs.chunks.stats().size和db.fs.chunks.stats().storageSize的比例——如果后者明显大于前者,往往说明仍有碎片或残留损坏块未清理干净
_mdb_catalog.wt 这样的元数据根文件丢失。不同损坏场景对应的恢复工具、操作顺序和风险控制完全不同,任何一步处理失误,都可能把原本还能抢救的数据彻底覆盖。