不能。分片集群中直接对mongos执行mongorestore会写入数据但未注册元数据,导致mongos无法路由;必须先恢复config server的shards、databases、collections、chunks四集合,再向对应分片写入数据,最后执行flushRouterConfig刷新路由缓存。

分片集群里不能直接用 mongorestore 恢复单个数据库?
不能。分片集群的元数据(如 config.shards、config.collections)和分片路由信息必须一致,否则 mongorestore 即使成功写入某个分片,mongos 也查不到该库——它根本不知道这个库该路由到哪。你看到的是空库或“collection not found”错误。
常见误操作:把备份目录下 mydb/ 直接传给 mongorestore --db mydb,目标连 mongos。结果是数据进了某个分片,但 config server 没注册,mongos 不认。
必须先还原 config server 的元数据
单个数据库恢复的前提,是让 config server 知道这个库存在、分片规则是什么、chunk 分布在哪。否则整个恢复链就断了。
- 从备份中提取
config数据库的shards、databases、collections、chunks四个集合的 BSON 文件 - 停掉所有
mongos实例(避免路由缓存干扰) - 用
mongorestore向 config server(不是 mongos!)单独恢复这四个集合,加--drop保证干净:
mongorestore --host config01:27019 --db config /path/to/backup/config/shards.bson --drop mongorestore --host config01:27019 --db config /path/to/backup/config/databases.bson --drop mongorestore --host config01:27019 --db config /path/to/backup/config/collections.bson --drop mongorestore --host config01:27019 --db config /path/to/backup/config/chunks.bson --drop
注意:config server 必须是可写状态(即非仲裁节点、且已启用 --configsvr 启动参数);若用副本集,需对 primary 执行。
再向对应分片写入实际数据
确认元数据已生效后,才能往分片写数据。关键点在于:必须只写入该数据库实际归属的分片(根据 config.chunks 查),而不是所有分片都跑一遍。
- 查出
mydb的分片归属:db.getSiblingDB("config").chunks.find({ns: "mydb.*"}).toArray() - 假设结果里只出现
shard01和shard02,那就只向这两个分片执行mongorestore - 命令要指定分片地址(不是 mongos),并带上
--noIndexRestore(索引会由分片自动重建,手动建可能错位):
mongorestore --host shard01:27018 --db mydb /path/to/backup/mydb/ --noIndexRestore --drop mongorestore --host shard02:27018 --db mydb /path/to/backup/mydb/ --noIndexRestore --drop
别漏掉 --drop:分片上可能残留旧 chunk 或 orphaned doc,不清理会导致查询结果混乱。
最后强制刷新路由表并验证
config server 更新后,mongos 不会立刻感知。必须手动触发刷新,否则仍查不到数据。
- 重启所有
mongos进程(最稳妥) - 或连接任意
mongos执行:db.adminCommand({flushRouterConfig: 1}) - 验证是否生效:
use mydb; db.runCommand({listCollections: 1}),再查几个 collection 的 count 是否匹配备份前数值
最容易被忽略的是 flushRouterConfig 这一步——很多人以为 config 写完就自动同步,其实 mongos 有本地缓存,不刷就不会加载新路由规则,导致“数据明明在,就是查不到”。


















