排查MongoDB性能问题时,运维人员的第一反应几乎都是先执行一次db.serverStatus()。这条命令返回的是当前mongod实例的实时运行快照,涵盖了连接、内存、存储引擎、操作统计、网络等各个维度的上百个指标。看懂这份输出,等于拿到了数据库的体检报告。本文从基本用法入手,逐步拆解各个关键字段的含义,并给出实际排查中需要重点关注的异常信号。

ServerStatus的基本用法
db.serverStatus()可以在mongo shell中直接执行,不需要额外权限(前提是当前用户具有clusterMonitor或root角色)。执行后返回一个大型的JSON文档。如果只需要查看某个部分,可以传入过滤参数,例如db.serverStatus({metrics:0, locks:0})可以省略metrics和locks部分,减少输出干扰。
最常用的做法是只看顶层字段:db.serverStatus().connections、db.serverStatus().mem、db.serverStatus().opcounters。这种点号取值的方式在快速排查时非常高效。此外还可以通过db.serverStatus().host、.version、.process确认当前连接的是哪个实例、哪个版本的mongod,避免在生产环境看错了机器。
// 查看整体概览
db.serverStatus()
// 只查看连接信息
db.serverStatus().connections
// 只查看操作计数
db.serverStatus().opcounters
// 查看实例基本信息,确认连的是哪台机器
db.serverStatus({host: 1, version: 1, process: 1, uptime: 1})
需要注意的是,serverStatus的部分计数器字段在3.0版本之后有较大调整,比如全局锁相关指标被移到了globalLock和存储引擎各自的统计中,网上一些老文章的字段说明已经过时,阅读时要以当前版本的实际输出为准。
关键字段逐一解读
connections:连接情况
connections块包含current(当前连接数)、available(剩余可用连接数)和totalCreated(累计创建过的连接数)。如果current不断攀升并接近current + available这个上限,说明应用侧可能存在连接泄漏,或者连接池配置过大。totalCreated增长速度过快则往往意味着客户端在频繁建立新连接,而没有复用连接池。
opcounters:操作计数
opcounters记录了自实例启动以来insert、query、update、delete、getmore、command六类操作的累计次数,配合opcountersRepl(复制集回放的计数)可以估算读写比例。单看一次快照意义不大,建议每隔几秒采样一次,相减得到每秒操作数,这才是衡量负载的直接依据。
// 简易采样脚本:每2秒输出一次每秒操作数
var prev = db.serverStatus().opcounters;
setInterval(function() {
var cur = db.serverStatus().opcounters;
print(
"query/s: " + (cur.query - prev.query) / 2 +
", insert/s: " + (cur.insert - prev.insert) / 2 +
", update/s: " + (cur.update - prev.update) / 2 +
", delete/s: " + (cur.delete - prev.delete) / 2
);
prev = cur;
}, 2000);
globalLock与队列:判断是否拥堵
globalLock.currentQueue中的total、readers、writers表示正在排队等待的操作数量。健康状态下队列应该基本为零,如果持续大于0且不断增长,说明请求处理速度跟不上到达速度,数据库已经出现拥堵。结合globalLock.activeClients可以进一步判断是读拥堵还是写拥堵。
mem与wiredTiger:内存与缓存
mem块展示物理内存和虚拟内存的占用情况,单位是MB。对于WiredTiger存储引擎,更值得关注的是wiredTiger.cache中的指标:"bytes currently in the cache"表示缓存中的数据量,"maximum bytes configured"是缓存上限(默认约为物理内存的50%)。如果缓存已满且"pages evicted"(被淘汰的页数)持续走高,通常意味着工作集大于缓存,查询需要频繁从磁盘读取数据,性能会明显下滑,此时要么扩内存,要么审视索引和查询模式。
// 查看WiredTiger缓存使用情况 db.serverStatus().wiredTiger.cache["bytes currently in the cache"] db.serverStatus().wiredTiger.cache["maximum bytes configured"] // 查看缓存命中率相关:未命中后从磁盘读入的页数 db.serverStatus().wiredTiger.cache["pages read into cache"]
metrics与network:网络与游标
network块记录进出流量字节数和请求数,用于判断网络是否成为瓶颈。metrics.cursor中的open.total和timedOut值得定期检查:打开的游标数量异常增长,常见原因是应用没有及时耗尽或关闭游标,可能导致内存持续占用;timedOut统计的是因超时被服务端强制关闭的游标数。
实际排查思路与注意事项
拿到一份serverStatus输出后,建议按固定顺序过一遍:先看uptime确认实例是否刚重启过,重启会导致所有计数器清零,采样对比会失真;再看connections判断连接是否异常;接着看队列和操作计数判断负载;最后看wiredTiger缓存判断内存压力。这个顺序能覆盖绝大多数常见的性能问题。
在复制集环境中,还可以结合repl块确认当前节点角色(PRIMARY或SECONDARY),以及repl.secondary中的复制延迟指标。在分片集群中,需要在每个分片和mongos上分别执行serverStatus,因为各实例只返回自身的数据,mongos层面还额外提供shardConnType、balancer相关统计,方便排查路由和均衡器问题。
最后提醒两点:一是serverStatus的输出每次执行都会有一定开销,监控系统的采集频率不宜过高,一般10到30秒一次足够;二是如果要做长期的趋势分析和告警,建议将serverStatus的采集接入Prometheus加Grafana或云监控平台,用图表观察指标变化,远比盯着单次快照有效。把单点排查和持续监控结合起来,才能真正掌握MongoDB的运行状态。
MongoDB ServerStatusdb.serverStatus数据库状态监控修改时间:2026-09-11 16:28:50