未分片集合默认存在于数据库绑定的 primary shard 上;该 primary shard 是数据库级设定,所有未分片集合均集中于此,不跨 shard 分布,且无法手动迁移。

未分片集合默认存在哪里?
所有未分片的集合(即没执行 shardCollection 的集合),都只存在于 primary shard 上,不会跨 shard 分布。这个 primary shard 是数据库级别的设定,不是集合级的——也就是说,一个数据库里所有未分片集合,全挤在它唯一的 primary shard 里。
常见错误现象:db.getMongo().getDBs() 看到某个库有数据,但 sh.status() 显示该库下所有集合都是 not sharded,却查不到它们在哪些 shard 上 —— 因为它们根本不在 shards 列表里显式列出,只隐式属于该库的 primary shard。
- 每个数据库创建时自动绑定一个 primary shard(通常是第一个加入集群的 shard)
- 可以用
db.runCommand({ movePrimary: "mydb", to: "shard01" })手动切换,但会触发全库数据迁移(阻塞写入) - 切换后,新插入的未分片集合才进新 shard;旧集合仍留在原位置,不自动搬
怎么确认某个库的 primary shard?
直接查 config.databases 集合最准,它记录了每个库绑定的 primary 字段:
db.getSiblingDB("config").databases.findOne({ "_id": "myapp" })
返回类似:{ "_id" : "myapp", "primary" : "shard02", "partitioned" : true }。注意 partitioned 为 true 只表示该库启用了分片功能(允许建分片集合),和里面有没有真正分片的集合无关。
- 别依赖
sh.status()输出里的 “databases” 表格 —— 它只显示分片集合所在的库,对纯未分片库可能根本不列出来 -
db.getCollectionNames()在 mongos 上执行时,能列出未分片集合,但无法告诉你它们物理在哪;必须连到对应 shard 的mongod上查 - 如果误以为未分片集合会“自动均衡”,结果发现某个 shard 磁盘爆满而其他 shard 很空,大概率就是 primary shard 没调好
为什么不能把未分片集合手动迁到别的 shard?
MongoDB 不提供任何命令把未分片集合从 primary shard 搬到另一个 shard。这是设计限制,不是操作遗漏。
原因很实际:未分片集合没有 chunk、没有 shard key,系统无法切分或路由,也就没法用 moveChunk 或类似机制迁移。强行绕过(比如用 mongodump/mongorestore)等于重建集合,且期间丢失写入、破坏原子性。
- 想让集合跨 shard,唯一合法路径是先
sh.enableSharding("mydb"),再sh.shardCollection("mydb.mycoll", { "field": 1 }) - 即使集合当前为空,也必须指定有效 shard key 才能成功分片;空集合 + 无效 key(如
{}或{_id: "hashed"}但没建索引)会报错cannot shard collection - 分片后,
primary shard仅作为元数据入口,数据本身按 chunk 分散 —— 这和未分片时的“全量独占”有本质区别
primary shard 被误删或宕机了怎么办?
如果 primary shard 宕机且不可恢复,整个数据库的未分片集合将完全不可读写(mongos 会报 FailedToSatisfyReadPreference 或连接拒绝)。这不是配置问题,是架构硬依赖。
恢复路径只有两条:一是拉起原 shard(推荐);二是用 movePrimary 切换,但前提是你得先让目标 shard 在线且有足够空间容纳全部未分片数据。
- 切换前务必检查目标 shard 的磁盘剩余空间 ——
db.getSiblingDB("admin").runCommand({ getShardMap: 1 })可看各 shard 容量 - 执行
movePrimary后,原 shard 上的数据不会自动清理,要手动进原节点的mongod,用db.mydb.mycoll.drop()清理残留(否则下次切回去会冲突) - 没有“临时降级为单节点模式”的选项;mongos 永远按分片集群协议路由,哪怕只剩一个 shard
primary shard 的角色看着低调,其实是未分片数据的实际单点;它的磁盘、IO、可用性,直接卡住整库命脉。很多人调完分片集合就忽略它,直到某天发现日志里全是 NotMasterNoSlaveOk 或备份失败才回头查 —— 那时候往往已经积压了大量写入延迟。










