rs.status()是唯一能查到真实复制进度的命令,必须在主节点执行;连secondary会报“not master and slaveOk=false”错误;需紧盯members中health、state数值码、durableOpTime.ts三项核心字段。

rs.status() 是唯一能查到真实复制进度的命令,其他辅助命令只是估算或快照,容易误导判断。
必须在主节点执行 rs.status()
连 secondary 节点直接运行会报错:not master and slaveOk=false。这不是权限问题,而是设计限制:副本集元数据只由主节点维护。
先确认角色:rs.isMaster().ismaster 返回 true 才算主节点;如果当前连的是 secondary,rs.secondaryOk() 只能放开读权限,但 rs.status() 仍不支持——必须重连到 primary。
盯住 members 数组里的三个字段
rs.status().members 每个成员对象里,只看这三项:
-
health:值为1表示心跳正常;0表示失联超heartbeatTimeoutMillis(默认 10 秒),但要注意lastHeartbeat时间戳,短暂抖动可能还没触发故障转移 -
state:用数值码判断真实状态,1=PRIMARY、2=SECONDARY、7=ARBITER、8=DOWN;别信stateStr字符串,它可能缓存旧值(比如刚宕机的节点还显示"SECONDARY") -
optime.durableOpTime.ts:这才是真实同步位点;和主节点的rs.status().optimes.durableOpTime.ts做差值,才能算出精确延迟(单位是 oplog 序号,不是秒)
别信 rs.printSlaveReplicationInfo() 的“X secs behind”
这个输出是拿 optimeDate 和本地系统时间做减法得出的,一旦节点时钟不同步(哪怕差几百毫秒),结果就不可信。
真正要看延迟,得对比主节点和 secondary 的 durableOpTime.ts:
比如主节点是 Timestamp(1747052340, 3),secondary 是 Timestamp(1747052330, 1),说明落后 10 条 oplog 记录。
这 10 条对应多久?取决于写入压力——db.getSiblingDB("local").oplog.rs.stats().avgObjSize 和当前 QPS 才能估算。
secondary optime 长期不更新怎么办
先检查 syncSourceHost 是否为空;再看 lastHeartbeatRecv 时间是否停滞——如果这个时间没变,说明复制源已断连或拒绝同步。
此时 rs.status() 里该成员的 state 很可能还是 2(SECONDARY),但 health 已为 0,optime 却卡在旧值不动,这是典型“假活”状态,不能仅靠 stateStr 判断。


















