未分片集合必定全部存储在数据库绑定的primary shard上,无法分散;最准确的确认方式是查询config.databases集合中对应数据库文档的primary字段值。

未分片集合一定会全部落在数据库绑定的 primary shard 上,无法分散,这是设计使然——不是配置错了,而是根本没这个功能。
怎么确认当前库的 primary shard 是哪个?
别信 sh.status() 的输出,它对纯未分片库经常不显示。最准的方式是查 config.databases:
db.getSiblingDB("config").databases.findOne({"_id": "myapp"})
返回里看 primary 字段值,比如 "shard02"。注意 partitioned: true 只表示该库启用了分片功能(允许建分片集合),和里面有没有实际分片的集合无关。
常见误判:在 mongos 上执行 db.getCollectionNames() 能看到未分片集合,但完全不知道它们物理在哪;必须连到对应 shard 的 mongod 上才能查实。
为什么不能把未分片集合手动迁到别的 shard?
MongoDB 不提供任何命令迁移未分片集合,这不是操作遗漏,是硬性限制。
- 未分片集合没有
chunk、没有shard key,系统无法切分或路由,moveChunk类机制根本用不上 - 想“绕过”只能用
mongodump/mongorestore --drop重建,但这会丢失迁移期间写入、破坏原子性,且需业务停写或容忍短暂不可用 - 误以为“自动均衡”能解决,结果发现某个
shard磁盘爆满而其他shard很空,八成就是primary shard没调好,或者压根没规划好未分片数据的归属
怎样防止未分片表挤爆 primary shard?
核心思路不是“搬走”,而是“隔离”和“前置控制”:
- 新业务上线前,明确区分数据类型:高频读写+大容量数据 → 必须分片;元数据、配置表、日志归档表等低频小表 → 单独建库,并绑定到专用的轻量级
shard(比如只配 16GB 内存的小规格节点) - 用
db.runCommand({ movePrimary: "myconfigdb", to: "shard03" })主动把配置类库的primary shard切到低负载节点,注意该操作会阻塞写入,且只影响后续新建的未分片集合,旧集合不动 - 监控
storageSize / dataSize比值,如果某shard上该比值长期 > 2.5,再叠加未分片集合持续增长,说明碎片+集中写入已在恶化磁盘压力 - 绝对不要把未分片集合和分片集合混在一个库里——看似省事,实则让
primary shard承担双重压力,还干扰balancer对分片集合的判断
最容易被忽略的一点:未分片集合的 primary shard 是数据库级绑定,一旦设错,修复成本远高于前期规划。上线前花十分钟查一次 config.databases,比后期半夜扩容 shard01 磁盘要实在得多。











