config数据库无mdl锁,但config.chunks因高频读写、全量扫描及索引限制易成瓶颈;排查重点是识别长时扫描、写失败和重复查询,而非锁类型。

config 数据库本身不产生“元数据锁冲突”——它没有 MySQL 那种 MDL,但它的集合(尤其是 config.chunks)会被高频读写,引发锁争用和查询阻塞。排查重点不是“锁类型”,而是“谁在反复扫、谁在长时间占、谁在写失败”。
为什么 config.chunks 会成为瓶颈?
这个集合存了所有分片集群的 chunk 范围、版本号、归属分片,10 万 chunk 就有 40–60MB BSON 数据。它被以下操作强制全量或范围扫描:
-
mongos每次路由查询前查 chunk 分布(尤其广播查询时) - 均衡器每 10 秒轮询一次,读
config.chunks+config.migrationJobs+config.locks -
sh.status()或sh.printShardingStatus()全量遍历该集合 - 每次 chunk 拆分/合并都触发写入 + 索引更新
关键点:config.chunks 的 B-tree 索引无法跳过范围扫描;MongoDB 6.0 不支持给它配只读副本,所有请求都打向主 config server。
怎么确认是 config.chunks 扫描拖慢了?
别只看 CPU 或磁盘,直接查实时操作和锁指标:
- 执行
db.getSiblingDB("config").currentOp({"secs_running": {"$gt": 5}, "ns": "config.chunks"}),看有没有 >5 秒还在扫config.chunks的操作 - 运行
db.getSiblingDB("config").serverStatus().metrics.lock,重点关注acquireWaitCount在database或collection级是否突增 - 用
mongotop -d config观察config.chunks的 read / write 时间占比是否长期 >70%
如果 sh.status() 响应超过 10 秒,且 mongotop 显示 config.chunks 占用高,基本就是它在拖。
哪些操作最容易触发 config server 锁争用?
不是所有操作都平等——有些行为会把 config server 推到临界点:
- 在低基数字段上分片(如
{status: 1}),导致数百个极小 chunk,config.chunks条目爆炸式增长 - 未禁用已下线数据库:
sh.disableSharding("old_db")没执行,其config.collections和关联 chunk 条目仍保留在元数据中 - 频繁手动触发
sh.splitAt()或sh.splitFind(),尤其在没预估好 chunk size 的情况下 - 均衡窗口设为全天开启,且
chunkSize过小(如默认 64MB),导致拆分/合并过于频繁
注意:sh.moveChunk 本身不会直接锁 config.chunks,但它失败后残留的 config.migrations 文档(state 为 catching_up 或 cloning)会持续触发校验查询,间接加重负担。
怎么安全清理和降压?
目标不是“清空”,而是“少读、少写、少扫”:
- 合并相邻小 chunk:
sh.mergeChunks("db.coll", {shardKey: min}, {shardKey: max}),必须确保连续且同属一个分片 - 调大
chunkSize:设为 128MB 或更高,降低拆分频率(需评估单个 chunk 写入压力) - 缩窄均衡窗口:
db.getSiblingDB("config").settings.update({_id:"balancer"}, {$set: {activeWindow: {start:"02:00", stop:"04:00"}}}, {upsert:true}) - 禁用非必要数据库:
sh.disableSharding("old_db"),再删掉对应 collection(若已无数据)
最后提醒一句:不要试图给 config 库加索引或改存储引擎——它是 MongoDB 内部管理集合,任何手动干预都可能导致集群不可用。











