checkMetadataConsistency 返回 InconsistentIndex 表示分片集群中各 shard 的索引元数据不统一,而非数据不一致;需连 mongos 执行该命令,重点分析 details.namespace 和 details.info 中缺失或冲突的索引名,并以 stateStr: "PRIMARY" 的 shard 为权威参考。

checkMetadataConsistency 返回 InconsistentIndex 怎么看
这不是数据不一致,而是分片集群中各 shard 的索引定义(元数据)不统一。典型错误日志如 CannotCreateCollection: aborting, shard is missing 1 indexes 就是直接信号。运行命令必须连到 mongos:
db.adminCommand({ checkMetadataConsistency: 1, checkIndexes: true })
重点看返回结果里的 details.namespace(例如 "test.users")和 details.info 中描述的缺失或冲突索引名。不要只扫一眼报错就动手——必须明确「哪个库、哪个集合、缺哪个索引」。
如果返回多个 InconsistentIndex 条目,优先以 stateStr: "PRIMARY" 所在 shard 的索引定义为权威参考;它通常是当前最新、最可信的版本。
为什么不能在 mongos 上用 getIndexes() 查索引
db.collection.getIndexes() 在 mongos 上执行,只返回路由层聚合视图,无法反映单个 shard 的真实索引状态。真正要查,必须分别连到每个 shard 的 PRIMARY 节点,执行:
db.collection.getIndexes({ full: true })
这个 full: true 很关键——它能暴露 hidden、unique、partialFilterExpression 等隐藏属性,小差异也会被 checkMetadataConsistency 判定为不一致。
常见坑:有人在某个 shard 上手动建了 background: true 的索引,但其他 shard 没同步,或者用了不同 collation,结果就被标记为不一致。
手动同步索引定义(不是数据)
目标是让所有 shard 的索引定义完全一致,不是复制数据目录,也不是重启 mongod。操作分三步:
- 过滤掉
_id_,只保留业务索引数组 - 对每个缺失索引的 shard,连其
PRIMARY,逐个执行createIndex(),参数必须一字不差(包括background、expireAfterSeconds、collation等) - 如果某个 shard 多出了不该有的索引,先确认该索引没被查询计划实际使用(查
explain("executionStats")),再执行dropIndex()
完成后再次运行 checkMetadataConsistency,确认 InconsistentIndex 条目消失;再观察几次 sh.status() 中的 chunk 分布和 balancer 状态,确保后续块迁移不再失败。
修复后最容易被忽略的关键点
createIndex 在 shard 上执行后,不会自动广播到 config 数据库的元数据里——它只影响本地 system.indexes(4.2+ 是 system.indexes 集合)。这意味着即使所有 shard 索引都“看起来一样”,查询优化器仍可能因 config server 缺失记录而跳过某些索引。
验证是否真生效,得在 mongos 上跑一个带该索引字段的查询,加 .explain("executionStats"),确认 indexName 出现在 executionStages 里,且 totalDocsExamined 显著低于全表扫描值。











