分片集群PITR必须先备份config server和所有shard,漏备任一组件将导致集群无法启动;需串行执行config备份、各shard带--oplog的mongodump并记录时间戳、恢复时先还原config再逐个还原shard并手动重建分片逻辑。

分片集群PITR必须先备份config server和所有shard
只备份某个shard或漏掉config server,恢复出来的集群根本起不来——mongos 启动时会从config server读取分片路由表,如果config数据不是跟shard快照同一时间点的,mongos 会报 Failed to load cluster ID from config server 或直接拒绝启动。
实操上要分三步串行执行:
- 用
mongodump备份config数据库(必须指定--db=config,不能只备份部分集合) - 对每个shard的副本集,分别在Secondary节点上执行带
--oplog的mongodump - 记录每个shard备份完成时的
oplog时间戳(通过rs.printReplicationInfo()查oldest timestamp)
恢复时不能直接 mongorestore 到分片集群
mongorestore 默认不处理分片元数据,它只是把BSON数据写进目标实例,但不会更新 config.collections、config.chunks 这些关键表。结果就是:数据文件里有数据,mongos 却查不到任何chunk,查询返回空。
正确流程是:
- 先停掉所有
mongos和shard节点,只保留config server副本集运行 - 用
mongorestore恢复config数据库到 config server(必须加--drop) - 逐个启动 shard 节点,但以
--replSet模式启动,不加入集群;再用mongorestore恢复各shard的数据目录(同样加--drop) - 最后手动调用
sh.addShard()和sh.enableSharding()重建分片逻辑
--oplog 参数在分片环境下的实际作用很有限
很多人以为加了 --oplog 就能做PITR,但在分片集群里,mongodump --oplog 只捕获单个shard副本集的oplog,而跨shard的事务(比如分布式事务)并不存在——MongoDB 5.0+ 的分布式事务依赖 config.transactions 表,它本身不记oplog,只靠 config 快照保证一致性。
所以真正能精确到秒的PITR,依赖的是:
- 所有shard的oplog起点时间戳必须对齐(通常取最早那个shard的oplog起始时间)
- config server的备份时间点必须 ≤ 所有shard oplog起点时间
- 恢复时重放oplog前,必须先用
db.getSiblingDB("local").oplog.rs.find().sort({$natural:-1}).limit(1)校验各shard oplog是否覆盖目标时间点
最容易被忽略的验证点:chunk分布与balancer状态
即使数据和config都恢复成功,如果没重置 config.settings 中的 balancer 开关,或者没清空 config.migrationHistory,balancer可能在恢复后立刻触发错误迁移,把刚恢复的数据又搬走。
安全做法是:
- 恢复完成后,先在
config库执行db.settings.updateOne({ _id: "balancer" }, { $set: { stopped: true } }) - 检查
config.chunks的lastmod字段,确认所有chunk的修改时间都在目标恢复时间点之前 - 手动运行
sh.status(),比对chunks数量与备份时刻是否一致(这个数字在备份日志里应该有记录)


















