checkmetadataconsistency 返回 inconsistentindex 表示分片集群中索引定义元数据不一致,而非数据不一致;典型原因是手动操作未同步或块迁移失败导致各 shard 索引不统一。

为什么 checkMetadataConsistency 会返回 InconsistentIndex
这不是数据不一致,而是分片集群的元数据(主要是索引定义)在不同 shard 上不统一。典型触发场景是:某个 shard 上手动执行了 createIndex 或 dropIndex,但没同步到其他 shard;或者块迁移中途失败,导致目标 shard 没来得及创建索引就退出了迁移流程。错误日志里常出现 "CannotCreateCollection: aborting, shard is missing 1 indexes" 就是这个信号。
确认哪些集合和索引有问题
先连到 mongos,运行:
db.adminCommand({ checkMetadataConsistency: 1, checkIndexes: true })
注意看返回结果中 details.namespace 字段(比如 "test.authors"),以及 details.info 里描述缺失或冲突的索引名。不要只扫一眼报错就动手——必须明确知道「哪个库、哪个集合、缺哪个索引」。
- 如果返回多个
InconsistentIndex文档,优先处理stateStr: "PRIMARY"所在 shard 的索引定义(它通常是权威参考) - 别用
getIndexes()在mongos上查——它只返回路由层视图,要分别连到每个 shard 的 PRIMARY 节点执行 - 检查时用
db.collection.getIndexes({ full: true }),确保看到hidden、unique、partialFilterExpression等完整属性,小差异也会被判定为不一致
手动同步索引定义(不是数据)
目标是让所有 shard 的 system.indexes(或 4.2+ 的 system.indexes 集合 + config database 元数据)完全一致。不能靠复制数据目录,也不能靠重启解决。
- 从 PRIMARY shard 获取索引定义:在该节点上运行
db.collection.getIndexes(),过滤掉_id_,只保留业务索引数组 - 对每个缺失索引的 shard,连到其 PRIMARY,逐个执行
createIndex,参数必须完全一致(包括background: true、collation、expireAfterSeconds等) - 如果某个 shard 多出了不该有的索引,直接
dropIndex——但务必确认该索引未被应用依赖(比如查询计划里是否用到) - 操作完成后,再次运行
checkMetadataConsistency,确认InconsistentIndex条目消失;再观察几次块迁移是否成功(sh.status()中balancer状态和chunks分布)
避免下次再出问题
元数据不一致本质是运维操作绕过了分片集群的协调机制。真正危险的不是修复动作本身,而是修复后没人验证索引是否真的被所有 shard 正确加载并参与查询优化。
最容易被忽略的一点:createIndex 在 shard 上执行后,不会自动广播到 config server 的 chunks 元数据里——它只影响本地 system.indexes。所以即使你补全了所有 shard 的索引,如果 config server 里没更新,下一次块迁移仍可能失败。验证方式是:在 mongos 上执行 db.collection.explain("executionStats").find({...}),确认 executionStats.nReturned 和 executionStats.executionStages.stage 显示用了预期索引,且没有 IXSCAN 降级成 COLLSCAN。











