.rollback目录中的.bson文件不能直接用mongorestore恢复,它们是mongodb崩溃时生成的oplog回滚快照,无集合元信息、结构松散、不保证完整,且不含.metadata.json;需先用bsondump逐个验证bson头有效性,再提取op:"i"/"u"操作的真实文档,按ts字段去重后导入。

rollback 目录里的 .bson 文件到底能不能直接用
不能直接 restore,它们不是标准 mongodump 输出格式,而是 MongoDB 崩溃恢复时写入的原始 oplog 回滚快照,结构松散、无集合元信息、可能跨多个文件且不保证完整。直接 mongorestore 会报 invalid BSON header 或静默跳过。
- 每个
.bson文件对应一次回滚操作的 oplog 条目(oplog.rs的子集),不是某个集合的 dump - 文件名如
test.mycol.2024-05-12T08-22-15.0.bson中的时间戳是回滚发生时间,不是数据写入时间 - 没有对应的
.metadata.json,所以mongorestore --dir无法识别目标集合和索引
用 bsondump 解析 rollback 文件前必须确认的三件事
bsondump 只能读取合法 BSON 流,而 rollback 文件里混有不完整记录、空字节、甚至非 BSON 二进制头——强行解析会卡住或输出乱码。
- 先用
head -c 4 filename.bson检查前 4 字节是否为小端整32位长度(常见值如\x1a\x00\x00\x00表示 26 字节),否则大概率是损坏或非 BSON 数据 - 确保 MongoDB 版本与
bsondump版本一致(例如 6.0 服务端产生的 rollback 文件,别用 4.4 的bsondump解) - 不要对整个 rollback 目录批量跑
bsondump:部分文件可能是空或仅含 header,会触发error: invalid length
安全做法是逐个试:
bsondump --outFile /dev/stdout test.mycol.2024-05-12T08-22-15.0.bson 2>/dev/null | head -n 5
从 bsondump 输出重建可导入的 JSON/CSV 需要过滤和补全字段
原始 oplog 条目是 { "ts": { "$timestamp": ... }, "h": ..., "op": "u", "ns": "test.mycol", "o2": { "_id": ... }, "o": { "$set": {...} } } 这类结构,不是用户数据本身。直接导出再 mongoimport 会失败。
- 只提取
"op": "i"(insert)、"op": "u"(update)中真正变更的文档内容,忽略"op": "d"(delete)和心跳 -
"o"字段在 update 操作里常是操作符(如$set,$inc),需用脚本展开成完整文档(例如结合"o2"中的_id构造最终状态) - 所有输出 JSON 行必须以
{开头、}结尾,且不含注释或换行嵌套——否则mongoimport --jsonArray会报invalid character
最小可用转换示例(用 jq):
bsondump ... | jq -r 'select(.op == "i") | .o' | grep -v "^null$" > insert.json
合并多份 rollback 数据时最易被忽略的顺序和去重逻辑
rollback 目录下可能有同集合多个时间戳文件,但它们不是按时间顺序覆盖,而是按崩溃瞬间的 WAL 刷盘顺序写入——后生成的文件不一定包含更新的数据,甚至可能倒序。
- 不能简单按文件名时间戳排序合并;必须解析每条记录的
"ts"字段({"$timestamp":{"t":1715502135,"i":1}}),转为 Unix 时间戳比对 - 同一
_id可能在多个文件中出现多次(例如 insert 后又 update),需按ts降序去重,保留最新一条 - 如果原库启用了
journal,rollback 数据可能只是局部状态,和主库当前 oplog 头部之间存在 gap,盲目全量导入会导致重复或丢失
真正能用的恢复路径只有两条:要么用 mongod --repair 尝试原地修复(要求数据目录未被覆盖),要么从最近一次有效备份 + oplog 增量重放——rollback 目录只是最后手段,且必须人工校验每条关键数据。










