mongodb的background:true并非完全不卡业务,根本原因在于写法错误(如多参数对象被忽略)、版本差异(3.6及之前仍持collection级ix锁)或wiredtiger缓存不足引发i/o压力。

不会完全阻塞,但具体是否影响业务,取决于 MongoDB 版本、索引大小、写入压力和 background 参数是否写对——4.2+ 基本无感,3.6 及之前版本“不锁库但可能卡写”,而写错语法则直接退化为前台锁库。
为什么 background:true 有时还是卡业务?
根本原因不是参数本身失效,而是写法错误或版本行为差异导致它被忽略:
-
db.coll.createIndex({a:1}, {name:"idx_a"}, {background:true})—— 三个大括号,MongoDB 只认第一个options对象,后两个被丢弃,background失效,退化为前台建索引 -
db.coll.ensureIndex({a:1}, {background:true}, {unique:true})—— 同样多对象,unique被当作独立参数传入,background不生效 - MongoDB 3.6 及更早:即使
background:true写对,仍会全程持有 collection 级IX锁,高频写入时可能短暂阻塞写操作(尤其批量 update)
4.2+ 版本的“后台”本质是啥?
从 4.2 开始,background 参数已被废弃,默认就是并发构建,锁只在两个瞬间出现:
- 开始注册元数据时:加短暂集合级
X锁(毫秒级) - 结束原子切换索引指针时:再加一次短暂
X锁 - 中间阶段全程只持
IS或IX锁,读写照常,QPS 波动极小 - WiredTiger 引擎下,只要不是每秒数万写入,基本感知不到
怎么确认当前建索引是不是真后台?
别信命令里写了 background:true,要现场验证:
- 执行
db.currentOp({ "op": "command", "command.createIndexes": { "$exists": true } }),看locks字段:
– 若有"Database":"w"或"Collection":"W",说明是前台锁;
– 若只有"Collection":"r"或"Collection":"w"且secs_running很小,大概率是 4.2+ 的两阶段模式 - 观察业务写入延迟:用
db.serverStatus().metrics.commands.insert.total对比建索引前后每秒 insert 数,突降 >30% 就说明有影响 - 查
db.coll.stats().indexCount是否随时间缓慢增加(后台模式是渐进式写入),而非建完才跳变
最易被忽略的一点:即便版本够新、语法正确,如果 WiredTiger 缓存配置过小(比如索引预计 10GB,cachesizegb 却只设 4GB),I/O 压力会飙升,间接拖慢业务——这不是锁的问题,但效果一样卡。











