serverstatus提供connections、metrics.commands、opcounters、mem、network等实时快照指标,需连主节点执行并加recordstats:0;重点关注游标、锁竞争、缓存、io压力及repl同步延迟。

直接看 serverStatus 能拿到哪些实时性能指标
它不是“分析工具”,而是一次性快照,但对排查瞬时瓶颈非常有效。关键字段包括 connections、metrics.commands、opcounters、globalLock(5.0 中已弃用,但 locks 和 storageEngine 下的 freelist、cache 更重要)、mem 和 network。特别注意 metrics.cursor.open 和 metrics.queryExecutor,它们反映查询执行器压力和游标堆积情况。
在副本集主节点上执行 serverStatus 的正确姿势
必须连到当前主节点,否则返回的是从节点视角(比如写入计数为 0)。先确认主节点:
rs.status().members.find(m => m.stateStr === 'PRIMARY').name
再连接并运行:
db.runCommand({ serverStatus: 1, recordStats: 0 })
-
recordStats: 0是必须加的,否则可能阻塞写入(尤其在高负载下) - 不要用
mongostat替代——它只聚合 opcounters,看不到锁等待、缓存命中率、游标状态等深层信息 - 如果连接的是仲裁节点或延迟从节点,
serverStatus仍可执行,但repl部分反映的是该节点自身同步状态,不能代表集群整体健康度
重点关注的字段组合与典型异常信号
单看一个值容易误判,要交叉验证:
-
mem.resident接近mem.logical?说明数据基本都在内存里;若mem.mapped远大于mem.resident,且extra_info.page_faults持续上升 → 磁盘 IO 压力大,可能缺索引或 RAM 不足 -
metrics.cursor.open.total高 +metrics.cursor.timedOut同步上涨 → 应用没正确关闭游标,或查询未加limit -
locks.Global.acquireCount.R和.W差距极大,但locks.Database.acquireWaitCount.W非零 → 写锁竞争严重,常见于高频更新同一文档或集合 -
storageEngine.wiredTiger.cache.maximum bytes configured与bytes currently in the cache接近 95%+,且pages evicted by application threads上升 → 缓存吃紧,考虑调大wiredTigerCacheSizeGB
如何用脚本持续采集并对比 serverStatus 快照
手动刷太慢,建议用简单 shell + mongo shell 组合做轻量监控:
echo 'db.runCommand({serverStatus: 1, recordStats: 0})' | mongo --quiet localhost:27017/admin > /tmp/ss_$(date +%s).json
- 别用
mongo --eval直接输出,容易被 shell 截断或转义破坏 JSON 结构 - 采集间隔建议 ≥ 5 秒,太密会增加主节点负担,尤其在
metrics开启后 - 对比两次快照时,优先算差值:比如
opcounters.insert差值 ÷ 时间差 = QPS;network.bytesIn差值 ÷ 时间差 = 实时吞吐 - 不要长期保留原始快照文件,
serverStatus输出体积随连接数和游标数线性增长,几个小时就可能达百 MB
serverStatus 的 repl 字段里 optimes.lastCommittedOpTime 和 lastVisibleOpTime 的差值,比 syncSourceHost 是否为空更能说明从节点是否真正跟得上——这个差值一旦超过几秒,多数写关注 "majority" 就开始卡住,但很多人只盯着 stateStr 看是不是 "SECONDARY"。











