内容提要
索引在MongoDB中起关键作用,提高查询性能和数据库效率。索引帮助导航到相关文档,避免集合扫描,适用于文档较多的集合,提高查询性能和用户体验。索引构建经历多个阶段,包括初始化、IX锁、集合扫描、处理临时写入表、处理约束违规表、设置索引为可用。构建索引时,MongoDB获取独占锁,停止对集合的读写操作。
延伸解读
锁机制如何影响业务可用性
索引构建过程中,MongoDB 会多次调整锁级别。初始阶段获取独占 X 锁,完全阻塞读写;随后降级为意向独占 IX 锁,允许读写操作;在提交前又提升为共享 S 锁,仅阻塞写操作;最后再次升级为 X 锁。这意味着构建索引并非全程无阻塞,尤其在开始和结束阶段,业务可能经历短暂但明显的写入停顿。对于写入频繁的集合,建议在低峰期执行索引构建,并关注构建期间客户端超时设置。
副本集环境下的提交仲裁
从 MongoDB 4.4 开始,索引构建需要副本集成员投票并等待 CommitQuorum 满足。主节点收集到足够票数后才会继续,从节点则等待复制到 commitIndexBuild 或 abortIndexBuild 的 oplog 条目。如果仲裁失败或从节点复制到中止条目,整个索引构建会被丢弃。这要求副本集成员健康且网络稳定,否则索引构建可能因投票不足而失败,需要重新发起。
唯一索引构建失败与重复键处理
构建唯一索引时,如果集合中存在重复值,MongoDB 会在集合扫描或处理侧写表阶段将冲突键记录到约束违规表。最终处理该表时,若仍有重复键,索引构建会以 E11000 错误失败,主节点写入 abortIndexBuild 通知从节点放弃。因此,在创建唯一索引前,应先用聚合或查询检查目标字段是否存在重复值,避免构建过程中断并产生不必要的清理开销。
侧写表与临时内存的使用
索引构建期间,新的写入操作生成的索引键会暂存到侧写表,构建完成后按 FIFO 顺序排空。集合扫描阶段,索引键在内存或临时磁盘文件中排序,日志显示 maxTemporaryMemoryUsageMB 为 200。如果集合很大或写入并发高,侧写表可能积累大量记录,延长构建时间并增加磁盘 I/O。监控构建日志中的 drained side writes 和内存使用参数,有助于评估构建对系统资源的影响。
Q&A
MongoDB中的索引有什么作用?
索引在MongoDB中提高查询性能和数据库效率,帮助直接导航到相关文档,避免集合扫描。
MongoDB索引构建的主要阶段有哪些?
索引构建主要经历初始化、IX锁、集合扫描、处理临时写入表、处理约束违规表、设置索引为可用等阶段。
在MongoDB中,构建索引时会发生什么?
构建索引时,MongoDB会获取独占锁,停止对集合的读写操作,并进行集合扫描和键生成。
什么是IX锁,它在索引构建中有什么作用?
IX锁是意向独占锁,允许在索引构建过程中进行读写操作,降低对集合的锁定程度。
MongoDB如何处理索引构建中的约束违规?
MongoDB会将键生成错误记录在约束违规表中,处理完成后再进行索引构建。
索引构建完成后,MongoDB会做什么?
索引构建完成后,MongoDB会将索引设置为可用,并释放独占锁。