必须手动执行flushrouterconfig命令,因为mongos不自动同步config server的分片变更,仅依赖默认30秒以上且易卡住的缓存刷新机制;sh.addshard()成功仅更新config server元数据,mongos本地路由表仍为旧列表,导致shardnotfound或空查询结果。

mongos 查不到新分片,不是配置没生效,是它根本没更新路由表缓存——必须手动执行 flushRouterConfig,否则永远找不到。
为什么 sh.addShard() 成功了但 mongos 还是报 ShardNotFound
因为 sh.addShard() 只改了 config server 的元数据,mongos 不会立刻拉取;它靠后台定时轮询同步,间隔默认 30 秒起,还可能因网络抖动卡住。此时 sh.status() 看起来正常(config server 已记录),但 mongos 本地缓存仍是旧分片列表。
- 现象:应用连 mongos 执行
db.collection.find()报ShardNotFound,或返回空结果 - 验证方式:在 mongos 上执行
db.runCommand({getShardMap: 1}),返回的shards字段里没有新分片 - 别试
rs.status()或查 config.shards 集合——那只是 config server 的状态,不是 mongos 看到的视图
怎么正确执行 flushRouterConfig
命令本身极简,但执行位置和时机错不得:
- 必须连到
mongos实例执行(不能连 config server,也不能连 shard) - 命令是:
db.runCommand({flushRouterConfig: 1}),无参数,不支持任何选项 - 成功返回
{"ok": 1};失败通常是因为权限不足(需 clusterAdmin 角色)或 mongos 正忙(重试即可) - 执行后该 mongos 进程立即重载全部路由信息,包括分片列表、zones、chunk 范围,毫秒级完成
哪些操作后必须刷,哪些不用刷
自动刷新机制不可信,只对极少数 config server 内部事件敏感。以下动作后,必须人工刷:
-
sh.addShard()或sh.removeShard()后——哪怕命令返回成功 - 手动调用
sh.splitAt()、sh.moveChunk(),或直接修改config.chunks后 - config server 主从切换、重启、或短暂失联恢复后
- MongoDB 升级后首次启动 mongos(尤其跨大版本,如 4.2 → 4.4)
而 sh.enableSharding()、sh.shardCollection() 这类集合级操作,一般会触发自动刷新,可不刷——但若后续查不到数据,第一反应仍是刷一次 flushRouterConfig。
flushRouterConfig 和 invalidateShardMetadata 别混用
invalidateShardMetadata 是另一个常被误用的命令,但它只清单个数据库或集合的路由元数据(比如分片键、chunk 范围),对分片拓扑完全无效。
- 适用场景:某个集合的 chunk 分布被绕过 sharding 命令直接改了(如误删
config.chunks文档),只想让 mongos 忘掉这个集合的缓存 - 不适用场景:新加了分片、删了分片、config server 换地址——这些都得靠
flushRouterConfig - 执行
invalidateShardMetadata后仍查不到新分片?说明你根本没碰对问题点
多个 mongos 实例要各自刷;脚本化运维时,别漏掉滚动更新中的新 mongos 进程——它们启动后不会自动同步其他 mongos 的缓存状态。











