Mongos重启后数据丢失问题疑因路由缓存导致
重启mongos后未分片集合数据丢失问题的修复与规避方案
问题重现步骤
- 在test数据库创建未分片的test集合:
use test db.test.insert({"k": 1})
- 手动修改
config.databases切换主分片:
use config db.databases.find({"_id": "test"}) { "_id" : "test", "primary" : "rs2_1", "partitioned" : false } db.databases.update({"_id": "test"}, {"$set": {"primary": "rs1_1"}}) db.databases.find({"_id": "test"}) { "_id" : "test", "primary" : "rs1_1", "partitioned" : false }
- 此时仍能正常查询数据:
use test db.test.find() { "_id" : ObjectId("63f74df722fe0bf5b3d2d284"), "k" : 1}
- 重启mongos进程:
kill 123 mongos -f /home/mongodb/mongo.conf
- 重启后查询不到数据:
db.test.find()
原因分析
- 未分片集合的路由依赖
config.databases中的primary字段指向的分片 - mongos会将路由信息缓存至内存,手动修改
config.databases不会触发内存缓存的更新,因此重启前仍能从原分片读取数据 - 重启mongos后,会重新加载
config.databases中的配置,此时路由指向新分片,但新分片并没有对应的数据,导致查询为空
修复方案
- 恢复路由并通过官方命令迁移数据
- 先将
config.databases中的primary改回原分片rs2_1,执行db.adminCommand({flushRouterConfig: 1})刷新mongos路由缓存(无需重启),确保能正常读取数据 - 使用MongoDB官方的
movePrimary命令迁移未分片数据库的主分片,该命令会自动同步数据、更新集群配置并刷新路由:db.adminCommand({movePrimary: "test", to: "rs1_1"}) - 迁移完成后,再次查询数据即可正常访问
- 先将
- 手动迁移数据至目标分片
- 如果无法恢复原配置,直接连接原分片
rs2_1,将test.test集合的数据导出,再导入到新分片rs1_1的对应数据库中,之后确认config.databases的primary配置正确
- 如果无法恢复原配置,直接连接原分片
规避方案
- 禁止手动修改
config库系统集合:config.databases、config.shards等属于集群核心配置集合,手动修改会导致配置与实际数据分布不一致,引发各类异常 - 使用官方命令调整分片:迁移未分片数据库主分片必须用
movePrimary命令,该命令会自动处理数据同步、配置更新和路由缓存刷新,保证集群状态一致 - 修改配置后强制刷新缓存:若特殊情况必须修改配置(不推荐),修改后需在所有mongos节点执行
db.adminCommand({flushRouterConfig: 1}),强制刷新内存路由缓存,避免重启后出现配置不一致
内容的提问来源于stack exchange,提问作者user10312673
相关产品推荐
相关产品推荐

