MongoDB 数据库连接超时与性能故障排查实战
一、故障背景
MongoDB 作为广泛使用的 NoSQL 数据库,在生产环境中常遇到连接超时、查询性能下降等问题。本文基于实际运维案例,系统梳理 MongoDB 常见故障的排查思路与解决方案。
二、连接超时故障排查
2.1 故障现象
- 应用端报错:
MongoServerError: connection timed out
- 连接池耗尽,新请求无法获取连接
- 部分请求成功,部分请求超时
2.2 排查步骤
步骤 1:检查 MongoDB 服务状态
1 2 3 4 5 6 7 8
| systemctl status mongod
netstat -tlnp | grep 27017
top -p $(pgrep -d',' mongod)
|
步骤 2:检查连接数
1 2 3 4 5 6 7 8
| mongosh --host localhost --port 27017
db.serverStatus().connections
db.currentOp({"secs_running": {"$gte": 10}})
|
关键指标解读:
current: 当前活跃连接数
available: 可用连接数
totalCreated: 累计创建连接数
连接数耗尽处理:
1 2 3 4
|
net: maxIncomingConnections: 65536
|
步骤 3:检查网络连通性
1 2 3 4 5 6 7 8 9 10 11
| telnet mongo-server 27017 nc -zv mongo-server 27017
iptables -L -n | grep 27017 firewall-cmd --list-ports
ping -c 10 mongo-server mtr mongo-server
|
步骤 4:分析慢连接
1 2 3 4 5 6 7 8 9 10 11 12
| db.setProfilingLevel(1, 100)
db.system.profile.find().sort({ts: -1}).limit(10)
db.currentOp().inprog.forEach(op => { if (op.secs_running > 5) { printjson(op) } })
|
2.3 常见原因与解决方案
| 原因 |
排查方法 |
解决方案 |
| 连接池配置过小 |
检查应用端连接池配置 |
增加 maxPoolSize |
| 网络延迟高 |
mtr/ping 测试 |
优化网络或就近部署 |
| 连接泄漏 |
分析 currentOp |
修复应用代码,设置 maxIdleTimeMS |
| 服务端连接数上限 |
查看 serverStatus |
调整 maxIncomingConnections |
| 防火墙拦截 |
检查 iptables/firewalld |
添加放行规则 |
三、查询性能故障排查
3.1 故障现象
- 查询响应时间突然变慢
- CPU 使用率飙升
- 磁盘 IO 等待增高
3.2 排查步骤
步骤 1:启用性能分析
1 2 3 4 5 6 7 8 9 10 11
| db.setProfilingLevel(1, 100)
db.system.profile.count()
db.system.profile.find( { millis: { $gt: 100 } }, { op: 1, ns: 1, query: 1, millis: 1, ts: 1 } ).sort({ millis: -1 }).limit(10)
|
步骤 2:检查索引使用情况
1 2 3 4 5 6 7 8 9 10 11 12 13 14
| db.collection.find({ status: "active" }).explain("executionStats")
db.collection.getIndexes()
db.serverStatus().metrics.commands.explain
db.system.profile.find({ "op": "query", "execStats.stage": "COLLSCAN" }).limit(10)
|
COLLSCAN 表示全表扫描,需要优化索引。
步骤 3:检查锁等待
1 2 3 4 5
| db.serverStatus().locks
db.currentOp().inprog.filter(op => op.locks && op.locks.Global.acquireWaitCount > 0)
|
步骤 4:检查内存与缓存
1 2 3 4 5 6 7 8 9 10
| db.serverStatus().mem
db.serverStatus().wiredTiger.cache
|
3.3 性能优化方案
方案 1:索引优化
1 2 3 4 5 6 7 8 9 10 11
| db.orders.createIndex({ customerId: 1, createdAt: -1 })
db.users.createIndex({ email: 1 }, { name: 1, status: 1 })
db.collection.dropIndex("unused_index")
db.collection.reIndex()
|
方案 2:查询优化
1 2 3 4 5 6 7 8 9 10 11 12
|
db.users.find({ name: /john/i })
db.users.find({ name: "John" })
db.users.find({ status: "active" }, { _id: 0, name: 1, email: 1 })
db.orders.find().sort({ createdAt: -1 }).limit(100)
|
方案 3:分片策略
1 2 3 4 5 6 7 8
| sh.enableSharding("production")
sh.shardCollection("production.orders", { customerId: "hashed" })
sh.status()
|
四、内存与磁盘故障排查
4.1 OOM 问题排查
1 2 3 4 5 6
| dmesg | grep -i "killed process" journalctl -k | grep -i "out of memory"
ps aux | grep mongod | awk '{print $6}'
|
解决方案:
1 2 3 4 5
| storage: wiredTiger: engineConfig: cacheSizeGB: 4
|
4.2 磁盘空间不足
1 2 3 4 5 6 7 8
| df -h
du -sh /var/lib/mongodb/*
db.collection.stats()
|
清理方案:
1 2 3 4 5 6 7 8
| db.logs.createIndex({ createdAt: 1 }, { expireAfterSeconds: 2592000 })
db.runCommand({ compact: "collection_name" })
db.collection.dropIndex("index_name")
|
4.3 磁盘 IO 性能问题
1 2 3 4 5 6 7 8
| iostat -x 1 5
mongostat --host localhost 1
db.serverStatus().metrics.storage
|
五、复制集故障排查
5.1 主从同步延迟
1 2 3 4 5 6 7 8
| rs.status()
rs.printSlaveReplicationInfo()
db.getReplicationInfo()
|
解决方案:
1 2 3 4
|
replication: oplogSizeMB: 10240
|
5.2 选举失败
1 2 3 4 5 6 7 8
| rs.conf().members.forEach(m => print(m.host, m.priority))
rs.stepDown()
tail -f /var/log/mongodb/mongod.log | grep -i election
|
六、监控与告警配置
6.1 Prometheus + MongoDB Exporter
1 2 3 4 5
| scrape_configs: - job_name: 'mongodb' static_configs: - targets: ['mongo-server:9216']
|
1 2 3 4 5
| docker run -d -p 9216:9216 \ --name mongodb-exporter \ percona/mongodb_exporter:0.40 \ --mongodb.uri="mongodb://user:pass@localhost:27017"
|
6.2 关键监控指标
| 指标 |
告警阈值 |
说明 |
| mongodb_connections_usage |
>80% |
连接池使用率 |
| mongodb_memory_usage |
>90% |
内存使用率 |
| mongodb_disk_usage |
>85% |
磁盘使用率 |
| mongodb_replication_lag |
>60s |
复制延迟 |
| mongodb_query_duration_avg |
>500ms |
平均查询耗时 |
| mongodb_asserts_regular |
持续增长 |
断言错误 |
七、故障排查流程图
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
| 连接超时/性能下降 ↓ 检查服务状态 (systemctl/netstat) ↓ 检查连接数 (serverStatus.connections) ↓ 检查网络连通性 (telnet/ping/mtr) ↓ 分析慢查询 (profiling) ↓ 检查索引使用 (explain) ↓ 检查锁等待 (currentOp) ↓ 检查内存/磁盘 (serverStatus.mem/cache) ↓ 定位问题并优化
|
八、总结
MongoDB 故障排查的核心思路:
- 先服务后网络:确认 MongoDB 服务正常,再排查网络问题
- 先指标后日志:通过 serverStatus 快速定位,再深入日志分析
- 先索引后查询:大部分性能问题源于索引缺失或使用不当
- 先监控后告警:建立完善的监控体系,提前发现问题
建立标准化的排查流程和监控体系,是保障 MongoDB 稳定运行的关键。
参考文档: