FATAL错误未必需修复,先判断是否真不可恢复:依据是断言编号或I/O错误(如Input/output error),而非盲目执行--repair;磁盘坏道需用smartctl和dd验证;能连shell则优先导出数据,完全启动失败时应只读挂载并离线提取BSON片段。

看到 FATAL 错误先别修,先确认它是不是真“不可恢复”
当 mongod 启动日志里反复出现 FATAL(比如 FATAL: WiredTiger error、FATAL: assertion 50717),很多人第一反应是立刻跑 mongod --repair。但现实是:WiredTiger 引擎从 MongoDB 4.4 起已彻底弃用 --repair 的数据修复能力,强行运行只会报错或静默失败——它现在只干一件事:把还能读的数据迁出到新目录,不修复损坏页本身。
真正能判断是否“不可恢复”的依据,是错误日志中带编号的断言(如 assertion 31367)或底层 I/O 报错(如 No such file or directory 对应 WiredTiger.wt 缺失,Input/output error 基本就是磁盘物理坏道)。这类错误一旦出现,说明元数据或检查点文件已损坏,WiredTiger 自身的日志重放(WAL)机制也救不回来。
- 用
tail -n 200 /var/log/mongodb/mongod.log | grep -i "fatal\|assertion\|error"提取关键行,重点看紧跟在FATAL后面的那条原始错误 - 如果错误含
WT_ERROR+handle-open或__wt_block_read,基本可判定为文件系统或磁盘层损坏,不是 MongoDB 配置问题 - 别信
df -h显示“还有空间”就排除磁盘故障——坏道可能只影响特定 block,smartctl -a /dev/sdX才是真相
磁盘级损坏的快速验证:绕过 MongoDB 直接读文件
WiredTiger 数据库本质是一堆 mmap 文件(WiredTiger.wt、WiredTiger.turtle、*.wt 集合文件)。若磁盘有坏块,这些文件用普通命令读就会暴露问题,比等 mongod 启动失败更早发现。
进数据目录(如 /var/lib/mongo),执行:
dd if=WiredTiger.wt of=/dev/null bs=64k count=100 2>&1 | grep -i "input/output\|invalid"
只要输出含 Input/output error,就坐实磁盘硬件问题。此时所有“修复”操作都该暂停,优先换盘或做 RAID 降级处理。
-
ls -l *.wt看文件大小是否异常(比如全是 0 字节或远小于正常值) - 用
file WiredTiger.wt检查文件头——正常应返回data,若报cannot open或显示乱码,说明文件系统层已损坏 - 切忌在疑似坏盘上反复运行
mongodump或db.validate(),这会加剧磁盘寻道压力,可能让坏块扩散
还能连上 shell?立刻导出可用数据,别碰 repairDatabase()
如果 mongod 能启动(哪怕部分集合打不开),但日志里有 FATAL,说明损坏是局部的。这时 db.repairDatabase() 是高危操作:它会重建所有索引并丢弃无法校验的文档,且**不支持 WiredTiger 引擎的在线修复**(MongoDB 官方已标记为 deprecated)。你更该做的是“抢救式导出”。
连接后立即执行:
use admin
db.runCommand({listDatabases: 1}).databases.forEach(d => {
print("dumping " + d.name);
// 强制全表扫描,跳过损坏索引
db.getSiblingDB(d.name).getCollectionNames().forEach(c => {
try { db.getSiblingDB(d.name)[c].find({}).limit(1).toArray() }
catch(e) { print("skip " + d.name + "." + c + ": " + e) }
})
})- 用
mongodump --forceTableScan --db <name> --collection <coll></coll></name>替代常规 dump,它绕过索引直接读数据页,对部分损坏更鲁棒 - 导出时加
--gzip --archive=backup.gz减少 I/O 压力,避免中途因磁盘响应慢而中断 - 若某集合执行
db.collection.stats()报EOF或Invalid argument,说明该集合文件已损坏,跳过即可,别硬试validate()
完全起不来?用只读挂载+离线提取,放弃“修复”幻想
当 mongod 连前台启动都失败(forked process exited with 1),且日志明确指向 WiredTiger.wt 或 WiredTiger.turtle 缺失/损坏,说明检查点元数据已毁。此时唯一现实路径是:把整个数据目录当成“只读硬盘镜像”,用外部工具提取尚存的 BSON 片段。
方法是将原盘挂载为只读(防止写入扩大损坏),然后用社区工具 wt(WiredTiger 官方调试工具)尝试 dump:
sudo mount -o ro,noatime /dev/sdX /mnt/bad-disk cd /mnt/bad-disk # 若有 wt 工具(需编译 WiredTiger 源码获取) ./wt -C "cache_size=1G,log=(enabled=false)" -h . dump -x table:collection-123 > collection-123.bson
注意:wt 不是 MongoDB 自带命令,需单独编译;多数生产环境没装,所以更通用的做法是:用 strings + 正则粗筛 BSON 文本特征(如 "_id":{、"$oid"),虽然效率低但至少能捞回部分 JSON 化文档。
- 别在故障盘上创建任何新文件(包括 log、pid、socket),所有操作目标路径必须指向另一块健康磁盘
- 如果
WiredTiger.turtle损坏,WiredTiger 根本无法定位元数据位置,此时连wt都可能报no metadata found——那就只剩二进制搜索这一条路 - 所谓“恢复”,在此场景下真实含义是:从损坏快照里尽可能多地提取未被覆盖的原始 BSON 片段,而非还原成完整数据库


















