MongoDBNotes

第 24 章:故障排查

zjc 于 2026-01-24 发布

这是《MongoDB 零基础实战指南》的独立章节版。本章从概念、实操和生产排查三个视角展开,代码块保留了原书可直接运行的版本。 排障原则:先固定影响面和时间线,再定位层级,最后做可回滚止损。不要在未看指标前重启、切主或修改参数,避免破坏证据。

24.1 排查框架

confirm impact
  -> collect timeline
  -> check topology
  -> check resources
  -> check slow queries
  -> check application
  -> mitigate
  -> verify
  -> review

需要记录:

  1. 开始和恢复时间;
  2. 环境、集群、数据库;
  3. 错误率、延迟、可用性;
  4. 发布和配置变更;
  5. 依赖服务状态;
  6. 最终根因和动作。

24.2 连接失败

常见错误:

错误 排查
Connection refused 进程退出、端口、bindIp
Authentication failed 用户、密码、authSource
Timeout 网络或 DNS
No primary 选举、多数丢失
Not primary 写入 Secondary
ReplicaSetNoPrimary 拓扑发现异常

检查:

mongosh --host mongo1 --port 27017 -u admin -p --authenticationDatabase admin
ss -lntp | grep 27017

24.3 慢查询

定位:

db.setProfilingLevel(1, { slowms: 100, sampleRate: 1 })

查看:

db.system.profile
  .find()
  .sort({ ts: -1 })
  .limit(10)

执行计划:

db.orders.find({ user_id: "u_1001" })
  .explain("executionStats")

常见原因:

  1. COLLSCAN;
  2. 索引选择性差;
  3. 内存排序;
  4. 返回大文档;
  5. 聚合数据放大;
  6. cache 压力;
  7. 磁盘瓶颈。

24.4 写入延迟高

检查:

operation write latency
write conflicts
transaction duration
cache dirty pages
disk util
journal latency
replication lag
index count

处理:

  1. 控制写入速率;
  2. 拆小事务;
  3. 减少热点文档冲突;
  4. 检查索引数量;
  5. 评估磁盘性能;
  6. 降低 Secondary 压力;
  7. 扩展分片。

24.5 Cache 与磁盘

查看:

db.serverStatus().wiredTiger.cache

典型信号:

信号 可能
pages read into cache 高 工作集大于内存
dirty pages 高 写入过快或 checkpoint 慢
pages evicted 高 cache 竞争
disk util 高 IO 瓶颈
checkpoint duration 长 脏页或磁盘压力

止损:

  1. 停止重查询;
  2. 限制批处理;
  3. 扩容内存;
  4. 归档冷数据;
  5. 增加分片;
  6. 优化索引和工作集。

24.6 复制延迟

查看:

rs.printSecondaryReplicationInfo()
rs.status()

原因:

  1. Secondary 磁盘慢;
  2. 网络带宽不足;
  3. 重查询影响;
  4. 索引构建;
  5. 大量写入;
  6. 大事务;
  7. 初始同步。

处理:

  1. 停止 Secondary 重负载;
  2. 降低写入;
  3. 修复网络;
  4. 等待索引完成;
  5. 必要时重新同步;
  6. 切读回 Primary。

24.7 选举异常

检查:

rs.status()
db.hello()

原因:

  1. Primary 故障;
  2. 网络分区;
  3. 多数成员不可用;
  4. priority 配置错误;
  5. 节点资源异常;
  6. 心跳超时。

处理:

  1. 恢复多数成员;
  2. 检查网络;
  3. 恢复磁盘和进程;
  4. 手动 stepDown 前确认目标健康;
  5. 保留选举日志。

24.8 正在执行的长时间操作

查看:

db.currentOp({
  active: true,
  secs_running: { $gte: 60 }
})

终止:

db.killOp(opid)

注意:

  1. 确认不是事务协调关键操作;
  2. 记录操作来源;
  3. 应用端同时取消;
  4. 强杀是止损,不是根因修复;
  5. 必须追溯为什么无超时。

24.9 分片问题

常见现象:

现象 排查
查询广播 查询不带分片键
某 shard 慢 数据倾斜、热点、资源
迁移卡住 网络、目标空间、元数据
mongos 错误 路由缓存、Config 状态
chunk jumbo 分片键频率过高

查看:

sh.status()
use config
db.chunks.find({ ns: "shop.orders" })

24.10 数据不一致疑云

分层确认:

application sent?
  -> write ack?
  -> primary visible?
  -> majority committed?
  -> secondary read?
  -> application cache?
  -> downstream index?

处理前先保存:

  1. 文档 _id
  2. 请求 ID;
  3. 写关注和读偏好;
  4. 操作时间;
  5. oplog 或审计;
  6. 应用日志。

24.11 应急预案

故障 止损
无 Primary 恢复多数成员、降级写
磁盘将满 停批处理、扩容、清理临时文件
cache 压力 停重查询、限流、扩内存
复制延迟 Secondary 摘读、恢复资源
慢查询风暴 限流、kill、启用缓存
误删除 停写、备份、时间点恢复
分片迁移压力 暂停 balancer

本章小结

MongoDB 故障通常由查询、索引、cache、磁盘、复制、选举或分片路由共同造成。先用 serverStatusrs.status、Profiler、explain 和系统指标固定证据,再做可回滚动作。恢复后必须验证业务数据和复盘。

思考题

  1. 为什么排障初期不建议直接重启?
  2. secs_running 高的操作如何处理?
  3. 复制延迟的常见原因有哪些?
  4. 广播查询为什么代价高?
  5. 误删除后第一步应该做什么?