必须先排空数据并清理元数据,否则removeshard会卡在"ongoing";根本原因是未分片数据库仍以该分片为primary,需用moveprimary或dropdatabase解除绑定,再重复执行removeshard触发清理阶段,最终返回"stage":"completed"才可安全关闭节点。

不能直接删,必须先排空数据再清理元数据,否则 removeshard 会卡在 "state":"ongoing" 且永远不结束。
removeshard 执行后卡在 draining ongoing 怎么办
这是最常见现象,根本原因不是迁移慢,而是有未分片的数据库(unsharded database)还绑定在该分片上作为 primary shard。即使所有分片集合的 chunk 都已迁走,removeshard 仍会阻塞。
- 运行
db.printShardingStatus(),检查每个数据库的primary字段,确认是否指向待删分片 - 对每个绑定的数据库执行
db.runCommand({ movePrimary: "dbname", to: "target_shard_name" })—— 注意这不是异步命令,需等返回{"primary":"target_shard_name","ok":1}再继续 - 如果数据库已无用,可直接
db.getSiblingDB("dbname").dropDatabase(),比movePrimary更快更彻底 - 执行完后,再跑一次
db.runCommand({ removeshard: "shard_name" }),状态应变为"state":"completed"
为什么必须重复执行 removeshard 命令
removeshard 是两阶段操作:第一阶段启动排空(draining),第二阶段清理 config server 中残留元数据。MongoDB 不自动触发第二阶段,必须手动再调一次命令。
- 首次执行返回
"state":"started"或"state":"ongoing" - 当
remaining: { chunks: 0, dbs: 0 }后,再次执行同一命令,才会进入清理阶段 - 最终成功标志是返回
"stage":"completed",此时才能安全关闭该分片的mongod进程 - 若跳过第二次执行,config.shards 集合里该分片的
draining字段仍为true,后续加回同名分片会失败
删除后想重新加入集群,为什么 mongod 启动失败或不写入数据
被移除的分片节点本地磁盘上仍残留旧集群的元数据(如 local 库、config 库副本、WiredTiger 日志),导致它拒绝加入新集群或无法承载新数据。
- 必须清空该节点的
--dbpath目录下所有文件(包括_mdb_catalog.wt等隐藏文件) - 不能只删
data子目录而保留journal或diagnostic.data;建议用rm -rf /path/to/dbpath/* - 重启前确保该节点未被任何
mongos缓存路由信息,必要时在所有mongos上执行db.runCommand({ flushRouterConfig: 1 }) - 重加时用
sh.addShard("shard_name/host:port"),而非复用旧配置
真正容易被忽略的是:movePrimary 和 removeshard 都依赖负载均衡器处于启用状态,但 movePrimary 过程中禁止写入——这点在业务高峰期极易引发超时或连接中断,务必安排维护窗口操作。











