MongoDB 用起来并不复杂,但实际开发、测试和服务器运维过程中,经常会遇到这样的情况:
text
数据库忘了怎么切换
Collection 怎么创建
用户怎么创建
密码怎么修改
索引怎么看
慢查询怎么排查
MongoDB 为什么连不上
27017 为什么没监听
认证为什么失败
磁盘为什么突然满了
怎么备份和恢复
Replica Set 怎么看状态
很多命令其实并不难,但隔一段时间不用就容易忘。
所以这篇文章整理一份比较完整的 MongoDB 常用命令和常见问题速查手册。
适合:
text
MongoDB 初学者
后端开发
Go / Java / Python / Node.js 开发
服务器运维
Docker 用户
MongoDB 生产环境排查
文中的命令主要基于:
text
mongosh
MongoDB 7.x / 8.x
Linux
来演示。
一、MongoDB 最常用的连接命令
最简单的连接:
bash
mongosh
默认连接:
text
mongodb://127.0.0.1:27017
也可以明确指定:
bash
mongosh mongodb://127.0.0.1:27017
指定服务器:
bash
mongosh --host 192.168.1.100
指定端口:
bash
mongosh \
--host 192.168.1.100 \
--port 27017
二、带用户名和密码连接
例如管理员用户:
text
用户名:admin
认证库:admin
执行:
bash
mongosh \
--host 127.0.0.1 \
--port 27017 \
-u admin \
-p \
--authenticationDatabase admin
执行以后终端会提示输入密码。
这种方式比较推荐,因为不会直接把密码暴露在:
text
Shell History
ps
命令日志
中。
三、使用 MongoDB URI 连接
例如:
bash
mongosh "mongodb://admin:password@127.0.0.1:27017/admin"
业务数据库:
bash
mongosh \
"mongodb://javapub_user:password@127.0.0.1:27017/javapub?authSource=javapub"
如果认证用户创建在 admin:
bash
mongosh \
"mongodb://javapub_user:password@127.0.0.1:27017/javapub?authSource=admin"
四、密码有特殊字符怎么办?
假设密码:
text
abc@123
不能直接:
text
mongodb://user:abc@123@127.0.0.1:27017
因为:
text
@
本身属于 URI 特殊字符。
应该 URL Encode:
text
abc%40123
于是:
text
mongodb://user:abc%40123@127.0.0.1:27017
常见特殊字符:
text
@ %40
: %3A
/ %2F
# %23
? %3F
% %25
这是 MongoDB 连接失败里非常常见的一个问题。
五、查看当前数据库
进入 mongosh 后:
javascript
db
可能看到:
text
test
六、查看所有数据库
javascript
show dbs
也可以:
javascript
show databases
七、切换数据库
例如:
javascript
use javapub
再次:
javascript
db
输出:
text
javapub
注意:
use javapub并不意味着数据库已经真正创建。
只有真正插入数据后,MongoDB 才会持久化这个数据库。
八、创建数据库
MongoDB 不需要显式:
sql
CREATE DATABASE
直接:
javascript
use javapub
插入数据:
javascript
db.users.insertOne({
name: "JavaPub"
})
此时数据库就会真正创建。
九、删除数据库
先切换:
javascript
use javapub
执行:
javascript
db.dropDatabase()
结果类似:
javascript
{
ok: 1,
dropped: "javapub"
}
生产环境一定慎用。
十、查看所有 Collection
javascript
show collections
也可以:
javascript
db.getCollectionNames()
例如:
javascript
[
"users",
"orders",
"articles"
]
十一、创建 Collection
通常没必要手动创建。
直接插入:
javascript
db.users.insertOne({
name: "JavaPub"
})
MongoDB 会自动创建:
text
users
如果需要显式创建:
javascript
db.createCollection("users")
十二、删除 Collection
javascript
db.users.drop()
返回:
text
true
十三、插入一条数据
javascript
db.users.insertOne({
name: "JavaPub",
age: 28,
email: "hello@example.com"
})
十四、插入多条数据
javascript
db.users.insertMany([
{
name: "Alice",
age: 20
},
{
name: "Bob",
age: 25
},
{
name: "Tom",
age: 30
}
])
十五、查询全部数据
javascript
db.users.find()
格式化查看:
javascript
db.users.find().pretty()
十六、查询一条数据
javascript
db.users.findOne()
指定条件:
javascript
db.users.findOne({
name: "JavaPub"
})
十七、等值查询
javascript
db.users.find({
name: "JavaPub"
})
多个条件:
javascript
db.users.find({
name: "JavaPub",
age: 28
})
这相当于:
text
name = JavaPub
AND
age = 28
十八、查询大于某个值
javascript
db.users.find({
age: {
$gt: 18
}
})
十九、大于等于
javascript
db.users.find({
age: {
$gte: 18
}
})
二十、小于
javascript
db.users.find({
age: {
$lt: 30
}
})
二十一、小于等于
javascript
db.users.find({
age: {
$lte: 30
}
})
二十二、不等于
javascript
db.users.find({
age: {
$ne: 18
}
})
二十三、范围查询
查询:
text
18 <= age <= 30
执行:
javascript
db.users.find({
age: {
$gte: 18,
$lte: 30
}
})
二十四、IN 查询
类似 SQL:
sql
WHERE age IN (18, 20, 25)
MongoDB:
javascript
db.users.find({
age: {
$in: [18, 20, 25]
}
})
二十五、NOT IN
javascript
db.users.find({
age: {
$nin: [18, 20, 25]
}
})
二十六、OR 查询
javascript
db.users.find({
$or: [
{
age: 18
},
{
name: "JavaPub"
}
]
})
相当于:
text
age = 18
OR
name = JavaPub
二十七、AND 查询
实际上:
javascript
db.users.find({
name: "JavaPub",
age: 28
})
默认就是 AND。
也可以写:
javascript
db.users.find({
$and: [
{
age: {
$gte: 18
}
},
{
age: {
$lte: 30
}
}
]
})
二十八、判断字段是否存在
查询有 email 字段的数据:
javascript
db.users.find({
email: {
$exists: true
}
})
查询没有 email:
javascript
db.users.find({
email: {
$exists: false
}
})
二十九、查询 NULL
javascript
db.users.find({
email: null
})
需要注意:
text
email: null
可能匹配:
text
email 本身为 null
或者字段不存在
如果只想找真正存在且为 null:
javascript
db.users.find({
email: null,
email: {
$exists: true
}
})
实际项目中可以根据数据结构进一步调整。
三十、模糊查询
例如查名字包含:
text
Java
可以:
javascript
db.users.find({
name: /Java/
})
忽略大小写:
javascript
db.users.find({
name: /javapub/i
})
也可以:
javascript
db.users.find({
name: {
$regex: "javapub",
$options: "i"
}
})
三十一、查询数组
例如:
json
{
"name": "JavaPub",
"tags": [
"Go",
"AI",
"Web3"
]
}
查询包含:
text
Go
javascript
db.users.find({
tags: "Go"
})
三十二、数组同时包含多个值
javascript
db.users.find({
tags: {
$all: [
"Go",
"AI"
]
}
})
三十三、查询数组长度
javascript
db.users.find({
tags: {
$size: 3
}
})
三十四、查询嵌套对象
数据:
json
{
"name": "JavaPub",
"profile": {
"city": "Beijing",
"website": "https://javapub.net.cn"
}
}
查询:
javascript
db.users.find({
"profile.city": "Beijing"
})
三十五、只返回指定字段
类似 SQL:
sql
SELECT name, age FROM users;
MongoDB:
javascript
db.users.find(
{},
{
name: 1,
age: 1
}
)
默认还会返回:
text
_id
如果不想要:
javascript
db.users.find(
{},
{
_id: 0,
name: 1,
age: 1
}
)
三十六、排序
年龄升序:
javascript
db.users.find().sort({
age: 1
})
降序:
javascript
db.users.find().sort({
age: -1
})
按照创建时间倒序:
javascript
db.users.find().sort({
created_at: -1
})
三十七、限制返回数量
只查 10 条:
javascript
db.users.find().limit(10)
三十八、跳过数据
跳过前 10 条:
javascript
db.users.find().skip(10)
三十九、分页查询
例如:
text
page = 2
pageSize = 10
执行:
javascript
db.users
.find()
.skip(10)
.limit(10)
计算公式:
text
skip = (page - 1) * pageSize
四十、统计数量
全部:
javascript
db.users.countDocuments({})
统计成年人:
javascript
db.users.countDocuments({
age: {
$gte: 18
}
})
四十一、修改一条数据
javascript
db.users.updateOne(
{
name: "JavaPub"
},
{
$set: {
age: 29
}
}
)
四十二、一次修改多个字段
javascript
db.users.updateOne(
{
name: "JavaPub"
},
{
$set: {
age: 29,
city: "Beijing",
status: 1
}
}
)
四十三、修改多条数据
javascript
db.users.updateMany(
{
age: {
$lt: 18
}
},
{
$set: {
status: "minor"
}
}
)
四十四、自增
年龄加 1:
javascript
db.users.updateOne(
{
name: "JavaPub"
},
{
$inc: {
age: 1
}
}
)
减少:
javascript
db.users.updateOne(
{
name: "JavaPub"
},
{
$inc: {
score: -10
}
}
)
四十五、删除字段
javascript
db.users.updateOne(
{
name: "JavaPub"
},
{
$unset: {
temp: ""
}
}
)
四十六、数组追加元素
javascript
db.users.updateOne(
{
name: "JavaPub"
},
{
$push: {
tags: "Docker"
}
}
)
四十七、避免数组重复
javascript
db.users.updateOne(
{
name: "JavaPub"
},
{
$addToSet: {
tags: "Docker"
}
}
)
如果已经存在:
text
Docker
就不会重复插入。
四十八、删除数组元素
javascript
db.users.updateOne(
{
name: "JavaPub"
},
{
$pull: {
tags: "Docker"
}
}
)
四十九、Upsert
如果存在则更新,不存在则创建:
javascript
db.users.updateOne(
{
email: "hello@example.com"
},
{
$set: {
name: "JavaPub",
age: 28
}
},
{
upsert: true
}
)
这是非常实用的写法。
五十、删除一条
javascript
db.users.deleteOne({
name: "JavaPub"
})
五十一、删除多条
javascript
db.users.deleteMany({
status: 0
})
五十二、清空 Collection
javascript
db.users.deleteMany({})
这会:
text
保留 Collection
删除全部 Document
如果:
javascript
db.users.drop()
则是:
text
Collection 本身也一起删除
五十三、创建普通索引
javascript
db.users.createIndex({
email: 1
})
五十四、创建唯一索引
javascript
db.users.createIndex(
{
email: 1
},
{
unique: true
}
)
五十五、创建联合索引
javascript
db.users.createIndex({
status: 1,
created_at: -1
})
五十六、查看索引
javascript
db.users.getIndexes()
五十七、删除索引
先查看:
javascript
db.users.getIndexes()
例如:
text
email_1
删除:
javascript
db.users.dropIndex("email_1")
删除所有非 _id 索引:
javascript
db.users.dropIndexes()
五十八、查看查询执行计划
javascript
db.users.find({
email: "hello@example.com"
}).explain()
更加详细:
javascript
db.users.find({
email: "hello@example.com"
}).explain("executionStats")
重点关注:
text
winningPlan
executionStats
totalDocsExamined
totalKeysExamined
nReturned
executionTimeMillis
如果:
text
totalDocsExamined
特别大,但:
text
nReturned
很小,通常说明查询可能缺少合适索引。
五十九、判断是否使用了索引
执行计划里看到:
text
IXSCAN
通常表示使用了索引。
如果看到:
text
COLLSCAN
表示:
text
全表扫描
数据量大时要重点关注。
六十、聚合:最简单的 Group By
假设:
json
{
"status": "paid",
"amount": 100
}
统计各状态数量:
javascript
db.orders.aggregate([
{
$group: {
_id: "$status",
count: {
$sum: 1
}
}
}
])
六十一、求和
javascript
db.orders.aggregate([
{
$group: {
_id: "$status",
totalAmount: {
$sum: "$amount"
}
}
}
])
六十二、平均值
javascript
db.orders.aggregate([
{
$group: {
_id: "$status",
avgAmount: {
$avg: "$amount"
}
}
}
])
六十三、聚合过滤
javascript
db.orders.aggregate([
{
$match: {
status: "paid"
}
},
{
$group: {
_id: null,
total: {
$sum: "$amount"
}
}
}
])
六十四、查看当前用户
javascript
db.runCommand({
connectionStatus: 1
})
也可以查看认证信息:
javascript
db.runCommand({
connectionStatus: 1,
showPrivileges: true
})
六十五、查看数据库用户
切换:
javascript
use admin
执行:
javascript
db.getUsers()
六十六、创建管理员
javascript
use admin
执行:
javascript
db.createUser({
user: "mongoAdmin",
pwd: "YOUR_STRONG_PASSWORD",
roles: [
{
role: "root",
db: "admin"
}
]
})
六十七、创建业务用户
例如:
javascript
use javapub
执行:
javascript
db.createUser({
user: "javapub_app",
pwd: "YOUR_PASSWORD",
roles: [
{
role: "readWrite",
db: "javapub"
}
]
})
六十八、创建只读用户
javascript
db.createUser({
user: "javapub_readonly",
pwd: "YOUR_PASSWORD",
roles: [
{
role: "read",
db: "javapub"
}
]
})
六十九、修改用户密码
切换到用户所在数据库。
例如:
javascript
use javapub
然后:
javascript
db.changeUserPassword(
"javapub_app",
"NEW_PASSWORD"
)
七十、修改用户权限
javascript
db.updateUser(
"javapub_app",
{
roles: [
{
role: "readWrite",
db: "javapub"
}
]
}
)
七十一、删除用户
javascript
db.dropUser("javapub_app")
七十二、查看 MongoDB 服务版本
Linux:
bash
mongod --version
mongosh:
bash
mongosh --version
Shell 中:
javascript
db.version()
七十三、查看 Server 状态
javascript
db.serverStatus()
内容非常多。
七十四、查看连接数
javascript
db.serverStatus().connections
例如:
javascript
{
current: 20,
available: 838840,
totalCreated: 500
}
重点:
text
current
表示当前连接数量。
七十五、查看内存情况
javascript
db.serverStatus().mem
七十六、查看网络统计
javascript
db.serverStatus().network
七十七、查看数据库大小
javascript
db.stats()
按照 MB 显示:
javascript
db.stats({
scale: 1024 * 1024
})
某些版本中也可以使用:
javascript
db.stats(1024 * 1024)
七十八、查看 Collection 大小
javascript
db.users.stats()
七十九、查看当前正在执行的操作
javascript
db.currentOp()
只看活跃操作:
javascript
db.currentOp({
active: true
})
八十、终止某个操作
先:
javascript
db.currentOp()
找到:
text
opid
例如:
text
12345
然后:
javascript
db.killOp(12345)
生产环境慎用。
八十一、查看 Replica Set 状态
javascript
rs.status()
八十二、查看 Replica Set 配置
javascript
rs.conf()
八十三、判断当前节点是不是 Primary
javascript
db.hello()
关注:
text
isWritablePrimary
例如:
javascript
{
isWritablePrimary: true
}
说明当前是 Primary。
八十四、初始化 Replica Set
javascript
rs.initiate()
或者:
javascript
rs.initiate({
_id: "rs0",
members: [
{
_id: 0,
host: "10.0.0.11:27017"
}
]
})
八十五、添加 Replica Set 节点
javascript
rs.add(
"10.0.0.12:27017"
)
再添加:
javascript
rs.add(
"10.0.0.13:27017"
)
八十六、移除节点
javascript
rs.remove(
"10.0.0.13:27017"
)
八十七、查看同步信息
javascript
rs.printReplicationInfo()
查看 Secondary:
javascript
rs.printSecondaryReplicationInfo()
八十八、主动让 Primary 降级
javascript
rs.stepDown()
也可以:
javascript
rs.stepDown(60)
表示:
text
60 秒内不参与 Primary 竞争
生产环境谨慎执行。
八十九、备份整个 MongoDB
bash
mongodump \
--uri="mongodb://USER:PASSWORD@127.0.0.1:27017/admin"
默认创建:
text
dump/
目录。
九十、指定备份目录
bash
mongodump \
--uri="mongodb://USER:PASSWORD@127.0.0.1:27017/admin" \
--out=/backup/mongodb
九十一、只备份一个数据库
bash
mongodump \
--uri="mongodb://USER:PASSWORD@127.0.0.1:27017/javapub?authSource=admin" \
--db=javapub \
--out=/backup/mongodb
九十二、压缩备份
bash
mongodump \
--uri="mongodb://USER:PASSWORD@127.0.0.1:27017/admin" \
--archive=/backup/mongodb.archive \
--gzip
九十三、恢复
bash
mongorestore \
--uri="mongodb://USER:PASSWORD@127.0.0.1:27017/admin" \
/backup/mongodb
九十四、恢复 Archive
bash
mongorestore \
--uri="mongodb://USER:PASSWORD@127.0.0.1:27017/admin" \
--archive=/backup/mongodb.archive \
--gzip
九十五、恢复前删除原 Collection
bash
mongorestore \
--drop \
--uri="mongodb://USER:PASSWORD@127.0.0.1:27017/admin" \
/backup/mongodb
注意:
text
--drop
非常危险。
九十六、导出 JSON
bash
mongoexport \
--uri="mongodb://USER:PASSWORD@127.0.0.1:27017/javapub" \
--collection=users \
--out=users.json
九十七、导出 CSV
bash
mongoexport \
--uri="mongodb://USER:PASSWORD@127.0.0.1:27017/javapub" \
--collection=users \
--type=csv \
--fields=name,age,email \
--out=users.csv
九十八、导入 JSON
bash
mongoimport \
--uri="mongodb://USER:PASSWORD@127.0.0.1:27017/javapub" \
--collection=users \
--file=users.json
九十九、导入 JSON Array
如果文件:
json
[
{
"name": "Alice"
},
{
"name": "Bob"
}
]
需要:
bash
mongoimport \
--uri="mongodb://USER:PASSWORD@127.0.0.1:27017/javapub" \
--collection=users \
--file=users.json \
--jsonArray
一百、查看 MongoDB 服务状态
Linux:
bash
sudo systemctl status mongod
启动:
bash
sudo systemctl start mongod
停止:
bash
sudo systemctl stop mongod
重启:
bash
sudo systemctl restart mongod
开机启动:
bash
sudo systemctl enable mongod
取消:
bash
sudo systemctl disable mongod
一百零一、查看 MongoDB 日志
Ubuntu / Debian:
bash
sudo tail -f \
/var/log/mongodb/mongod.log
最后 200 行:
bash
sudo tail -n 200 \
/var/log/mongodb/mongod.log
systemd:
bash
sudo journalctl -u mongod
实时:
bash
sudo journalctl \
-u mongod \
-f
一百零二、检查 27017 是否监听
bash
sudo ss -lntp \
| grep 27017
或者:
bash
sudo lsof -i :27017
一百零三、常见问题:MongoDB 启动失败
先执行:
bash
sudo systemctl status mongod
然后:
bash
sudo journalctl \
-u mongod \
-n 200
最后:
bash
sudo tail \
-n 200 \
/var/log/mongodb/mongod.log
MongoDB 启动失败不要第一时间重装。
日志基本都会告诉你原因。
一百零四、常见问题:Unit mongod.service not found
执行:
bash
systemctl status mongod
出现:
text
Unit mongod.service could not be found
常见原因:
text
MongoDB Server 没安装
安装的不是官方 mongodb-org
软件包安装失败
检查:
bash
which mongod
再:
bash
mongod --version
Ubuntu:
bash
dpkg -l | grep mongo
CentOS:
bash
rpm -qa | grep mongo
一百零五、常见问题:Connection refused
报错:
text
MongoServerSelectionError
ECONNREFUSED
Connection refused
先:
bash
sudo systemctl status mongod
再:
bash
sudo ss -lntp \
| grep 27017
如果 MongoDB 没启动:
bash
sudo systemctl start mongod
如果服务器地址写错,也会出现这个问题。
一百零六、常见问题:本机能连接,远程连不上
检查:
bash
sudo ss -lntp \
| grep 27017
如果看到:
text
127.0.0.1:27017
说明 MongoDB 只监听本机。
配置:
bash
sudo vim /etc/mongod.conf
找到:
yaml
net:
port: 27017
bindIp: 127.0.0.1
例如修改:
yaml
net:
port: 27017
bindIp: 127.0.0.1,10.0.0.10
然后:
bash
sudo systemctl restart mongod
一百零七、不要随便 bindIp 0.0.0.0
虽然:
yaml
bindIp: 0.0.0.0
很方便。
但是意味着:
text
所有网卡都监听 27017
如果服务器还有公网 IP,并且安全组开放了:
text
27017
那么 MongoDB 很可能直接暴露公网。
推荐:
yaml
bindIp: 127.0.0.1,10.0.0.10
只监听:
text
本机
内网
一百零八、常见问题:Authentication failed
常见报错:
text
Authentication failed
不要第一反应认为密码一定错了。
MongoDB 认证失败最常见的原因之一是:
text
authSource 写错
假设用户创建在:
javascript
use admin
那么:
text
authSource=admin
例如:
text
mongodb://user:password@127.0.0.1:27017/javapub?authSource=admin
一百零九、如何确认用户创建在哪个数据库?
分别查看:
javascript
use admin
javascript
db.getUsers()
然后:
javascript
use javapub
javascript
db.getUsers()
MongoDB 用户是:
text
属于某个数据库的
不是完全独立的全局用户。
一百一十、常见问题:密码没错还是认证失败
检查:
text
用户名
密码
authSource
认证机制
URI 特殊字符
用户是否已经创建
用户权限
可以先使用:
bash
mongosh \
-u username \
-p \
--authenticationDatabase admin
如果命令行可以登录,但程序不行,就重点检查:
text
应用连接字符串
URL Encode
一百一十一、常见问题:not authorized
例如:
text
not authorized on javapub to execute command
意味着:
text
已经登录成功
但是权限不足
查看用户:
javascript
db.getUser("javapub_app")
检查:
text
roles
例如应用需要:
javascript
{
role: "readWrite",
db: "javapub"
}
一百一十二、常见问题:E11000 duplicate key error
经典错误:
text
E11000 duplicate key error
通常意味着:
text
违反唯一索引
例如:
javascript
db.users.createIndex(
{
email: 1
},
{
unique: true
}
)
又插入:
javascript
{
email: "hello@example.com"
}
已有相同值。
查看索引:
javascript
db.users.getIndexes()
一百一十三、创建唯一索引时报 E11000
如果原数据已经存在重复:
javascript
db.users.createIndex(
{
email: 1
},
{
unique: true
}
)
会失败。
可以先找重复:
javascript
db.users.aggregate([
{
$group: {
_id: "$email",
count: {
$sum: 1
},
ids: {
$push: "$_id"
}
}
},
{
$match: {
count: {
$gt: 1
}
}
}
])
先清洗数据,再建唯一索引。
一百一十四、常见问题:查询很慢
第一步:
javascript
db.users.find({
email: "hello@example.com"
}).explain("executionStats")
重点看:
text
COLLSCAN
如果数据量大,并且频繁按照:
text
email
查询,就应该考虑:
javascript
db.users.createIndex({
email: 1
})
一百一十五、不是所有字段都应该建索引
索引不是越多越好。
因为索引会增加:
text
磁盘占用
写入成本
更新成本
内存消耗
一般重点考虑:
text
高频查询字段
排序字段
联合查询字段
唯一字段
而不是每个字段都加索引。
一百一十六、联合索引顺序很重要
例如:
javascript
db.orders.createIndex({
user_id: 1,
created_at: -1
})
更适合:
javascript
db.orders.find({
user_id: 10001
}).sort({
created_at: -1
})
索引设计需要围绕:
text
实际查询模式
而不是单纯看字段。
一百一十七、常见问题:磁盘突然满了
检查:
bash
df -h
MongoDB 数据:
bash
du -sh /var/lib/mongodb
或者:
bash
du -sh /data/mongodb
日志:
bash
du -sh /var/log/mongodb
继续:
bash
du -ah /var/log/mongodb \
| sort -h \
| tail
一百一十八、不要直接删除 MongoDB 数据文件
不要看到:
text
/var/lib/mongodb
很大,就直接:
bash
rm -rf /var/lib/mongodb/*
这相当于:
直接物理删除数据库。
正常删除应该通过:
javascript
db.dropDatabase()
或者:
javascript
db.collection.drop()
并提前备份。
一百一十九、常见问题:日志文件太大
查看:
bash
ls -lh /var/log/mongodb
通常应该配合:
text
logrotate
查看:
bash
ls /etc/logrotate.d/
可以根据实际部署方式配置日志轮转。
不要让:
text
mongod.log
无限增长。
一百二十、常见问题:MongoDB 内存占用高
MongoDB 高内存使用并不一定代表:
text
内存泄漏
数据库通常会主动利用内存做:
text
缓存
WiredTiger Cache
索引
先看:
javascript
db.serverStatus().wiredTiger.cache
再结合:
bash
free -h
判断。
不要只看到 MongoDB 占用几个 GB 就立刻认为异常。
一百二十一、查看 WiredTiger Cache
javascript
db.serverStatus().wiredTiger.cache
重点可以观察:
text
maximum bytes configured
bytes currently in the cache
pages read into cache
pages written from cache
一百二十二、常见问题:Too many connections
先:
javascript
db.serverStatus().connections
如果:
text
current
非常高,要检查应用程序是否正确使用连接池。
例如错误模式:
text
每个 HTTP 请求
创建一次 MongoClient
然后不关闭
这是非常危险的。
正确方式通常是:
text
整个应用共享 MongoClient
使用驱动连接池
一百二十三、Go 项目不要每次请求都 Connect
错误思路:
go
func Handler() {
client, err := mongo.Connect(...)
// 每个请求都创建 client
}
更合理:
text
程序启动
↓
创建 Mongo Client
↓
建立连接池
↓
Handler / Service 共享
↓
程序退出再 Disconnect
一百二十四、常见问题:Server selection timeout
Go / Node 等驱动常见:
text
server selection timeout
常见原因:
text
MongoDB 服务没启动
IP 写错
27017 不通
bindIp 错误
防火墙拦截
安全组没开
Replica Set 配置错误
DNS 无法解析
首先:
bash
nc -vz 10.0.0.10 27017
一百二十五、使用 nc 测试 MongoDB 端口
bash
nc -vz 127.0.0.1 27017
远程:
bash
nc -vz 10.0.0.10 27017
成功:
text
Connection succeeded
失败:
text
Connection refused
说明服务或监听有问题。
如果:
text
timed out
则通常重点排查:
text
防火墙
安全组
网络路由
一百二十六、检查防火墙
Ubuntu:
bash
sudo ufw status
CentOS:
bash
sudo firewall-cmd --list-all
云服务器还要检查:
text
AWS Security Group
阿里云安全组
腾讯云安全组
Cloud Firewall
VPC ACL
一百二十七、常见问题:MongoDB 配置改了不生效
修改:
text
/etc/mongod.conf
以后一定要:
bash
sudo systemctl restart mongod
再看:
bash
sudo systemctl status mongod
以及:
bash
sudo ss -lntp \
| grep 27017
不能只修改配置却不重启。
一百二十八、常见问题:修改配置后 MongoDB 起不来
通常是:
text
YAML 缩进错误
字段拼错
目录不存在
目录权限错误
bindIp 配错
看日志:
bash
sudo journalctl \
-u mongod \
-n 100
YAML 最容易出现的问题就是:
yaml
security:
authorization: enabled
错误。
正确:
yaml
security:
authorization: enabled
一百二十九、常见问题:Permission denied
如果自定义:
text
/data/mongodb
需要:
bash
sudo chown \
-R mongodb:mongodb \
/data/mongodb
日志:
bash
sudo chown \
-R mongodb:mongodb \
/data/logs/mongodb
查看:
bash
ls -ld /data/mongodb
一百三十、常见问题:Address already in use
报错:
text
Address already in use
检查:
bash
sudo lsof -i :27017
或:
bash
sudo ss -lntp \
| grep 27017
可能是:
text
旧 MongoDB
Docker MongoDB
另一个 mongod
其他程序
一百三十一、检查 Docker 是否占用端口
bash
docker ps \
--format \
'table {{.Names}}\t{{.Ports}}'
如果看到:
text
0.0.0.0:27017->27017/tcp
说明 Docker 已经占用 27017。
一百三十二、Docker 查看 MongoDB 日志
bash
docker logs mongodb
实时:
bash
docker logs \
-f mongodb
最后 100 行:
bash
docker logs \
--tail 100 \
mongodb
一百三十三、Docker 进入 MongoDB
bash
docker exec \
-it mongodb \
mongosh
认证:
bash
docker exec \
-it mongodb \
mongosh \
-u mongoAdmin \
-p \
--authenticationDatabase admin
一百三十四、Docker 重启 MongoDB
bash
docker restart mongodb
查看:
bash
docker ps
一百三十五、Docker Compose 常用命令
启动:
bash
docker compose up -d
停止:
bash
docker compose stop
启动:
bash
docker compose start
重启:
bash
docker compose restart
删除:
bash
docker compose down
日志:
bash
docker compose logs -f mongodb
查看:
bash
docker compose ps
一百三十六、不要随便 docker compose down -v
普通:
bash
docker compose down
和:
bash
docker compose down -v
差别非常大。
-v 会删除相关 Volume。
如果数据库使用 Docker Volume 存储,很可能相当于:
把 MongoDB 数据一起删了。
生产环境慎用。
一百三十七、常见问题:Replica Set 不是 Primary
可能看到:
text
not primary
或者:
text
not writable primary
执行:
javascript
rs.status()
再:
javascript
db.hello()
确认当前节点角色。
应用程序最好连接:
text
Replica Set
而不是死连某一个节点并假设它永远是 Primary。
一百三十八、Replica Set 一直 STARTUP2
执行:
javascript
rs.status()
如果 Secondary 长时间:
text
STARTUP2
可以检查:
text
节点之间网络
27017 是否互通
hostname 是否可解析
数据量是否很大
同步是否正在进行
日志错误
认证 KeyFile
磁盘空间
一百三十九、Replica Set 节点互相测试
例如:
bash
nc -vz \
mongo2 \
27017
或者:
bash
nc -vz \
10.0.0.12 \
27017
Replica Set 不只是:
text
客户端 → MongoDB
能通。
还要求:
text
MongoDB 节点之间
能够通信。
一百四十、MongoDB 服务快速健康检查
我经常使用:
bash
mongosh \
--quiet \
--eval \
'db.adminCommand({ping:1})'
正常:
javascript
{
ok: 1
}
Docker Healthcheck 也可以使用这个思路。
一百四十一、Linux 一条命令检查 MongoDB
bash
systemctl is-active mongod
输出:
text
active
查看是否开机启动:
bash
systemctl is-enabled mongod
一百四十二、快速检查脚本
可以创建:
bash
vim check-mongodb.sh
写入:
bash
#!/bin/bash
echo "=== MongoDB Service ==="
systemctl status mongod \
--no-pager
echo
echo "=== MongoDB Port ==="
ss -lntp \
| grep 27017
echo
echo "=== MongoDB Version ==="
mongod --version \
| head
echo
echo "=== MongoDB Ping ==="
mongosh \
--quiet \
--eval \
'db.adminCommand({ping:1})'
echo
echo "=== Disk ==="
df -h
echo
echo "=== MongoDB Data Size ==="
du -sh \
/var/lib/mongodb \
2>/dev/null
授权:
bash
chmod +x check-mongodb.sh
执行:
bash
./check-mongodb.sh
一百四十三、MongoDB 排错推荐顺序
遇到:
text
MongoDB 用不了
不要一上来改一堆配置。
推荐按照这个顺序:
text
1. 服务有没有启动
2. 端口有没有监听
3. 本机能不能连接
4. 用户认证是否正常
5. bindIp 是否正确
6. 远程端口是否能通
7. 防火墙是否放行
8. 云安全组是否放行
9. authSource 是否正确
10. 用户权限是否足够
11. Replica Set 是否正常
12. 看 MongoDB 日志
对应命令:
bash
systemctl status mongod
bash
ss -lntp | grep 27017
bash
mongosh
bash
nc -vz IP 27017
bash
tail -n 200 /var/log/mongodb/mongod.log
这套流程能解决绝大多数 MongoDB 连接问题。
一百四十四、MongoDB 常用命令速查表
数据库:
javascript
show dbs
javascript
use javapub
javascript
db
javascript
db.dropDatabase()
Collection:
javascript
show collections
javascript
db.createCollection("users")
javascript
db.users.drop()
插入:
javascript
db.users.insertOne({})
javascript
db.users.insertMany([])
查询:
javascript
db.users.find()
javascript
db.users.findOne()
修改:
javascript
db.users.updateOne()
javascript
db.users.updateMany()
删除:
javascript
db.users.deleteOne()
javascript
db.users.deleteMany()
索引:
javascript
db.users.createIndex()
javascript
db.users.getIndexes()
javascript
db.users.dropIndex()
统计:
javascript
db.users.countDocuments({})
状态:
javascript
db.serverStatus()
javascript
db.currentOp()
Replica Set:
javascript
rs.status()
javascript
rs.conf()
javascript
db.hello()
一百四十五、Linux MongoDB 常用命令速查
服务:
bash
systemctl status mongod
bash
systemctl start mongod
bash
systemctl stop mongod
bash
systemctl restart mongod
日志:
bash
journalctl -u mongod -f
bash
tail -f /var/log/mongodb/mongod.log
端口:
bash
ss -lntp | grep 27017
版本:
bash
mongod --version
bash
mongosh --version
连接:
bash
mongosh
测试:
bash
nc -vz 127.0.0.1 27017
磁盘:
bash
df -h
bash
du -sh /var/lib/mongodb
一百四十六、最后总结
MongoDB 真正经常使用的命令其实并没有想象中那么多。
开发阶段重点掌握:
text
use
show dbs
show collections
find
insertOne
updateOne
deleteOne
aggregate
createIndex
explain
运维阶段重点掌握:
text
mongosh
systemctl
journalctl
ss
mongodump
mongorestore
serverStatus
currentOp
rs.status
排查 MongoDB 问题时,则始终记住:
text
服务
↓
端口
↓
网络
↓
认证
↓
权限
↓
索引
↓
磁盘
↓
Replica Set
↓
日志
MongoDB 很多所谓的"数据库故障",最后其实都是:
text
服务没启动
bindIp 错了
防火墙拦了
authSource 错了
权限不够
索引没建
磁盘满了
因此相比死记所有命令,更重要的是形成一套自己的排错顺序。
最后把最值得记住的几条命令留下:
bash
systemctl status mongod
bash
ss -lntp | grep 27017
bash
mongosh
javascript
show dbs
javascript
show collections
javascript
db.serverStatus()
javascript
db.currentOp()
javascript
db.users.getIndexes()
javascript
db.users.find({}).explain("executionStats")
javascript
rs.status()
bash
mongodump
bash
mongorestore
基本已经覆盖了日常开发和绝大部分 MongoDB 排错场景。
现在是最好的时代。中国有全世界最高性价比的制造业,有发达的网络和全球物流。
只要你愿意,你几乎可以买到这个世界上任何地方生产的、任何你想要的商品。你可以用很低的成本,撬动全球的资源为你服务。
不过,真正稀缺的,从来不是商品,而是注意力、判断力,以及把事情做成的能力。
所以,这是最好的时代,也是最坏的时代。
我是王仕宇,关注 AI、Web3 与开源,持续探索如何把技术做成产品,把产品转化为真实价值。