1. 为什么还要折腾 Ubuntu 16.04 上的 MongoDB 4.2
先把话说在前头:Ubuntu 16.04 这个系统版本放到今天确实不算新,官方标准支持周期早就结束了,很多新软件也陆续停止为它提供预编译包。但现实情况是,不少企业内部的老旧测试机、边缘设备、离线环境里的服务器,依然跑着 16.04。你没法说换就换,业务在跑,数据在存,迁移成本高得吓人。这时候如果还想用上 MongoDB 4.2 Community Edition,就得自己动手把环境搭起来。
MongoDB 4.2 这个版本在 NoSQL 圈子里算是一个分水岭。它引入了分布式事务、通配符索引、字段级加密这些重量级特性,同时保持了文档型数据库灵活的模式设计。Community Edition 是免费开源的社区版,功能上覆盖了绝大多数中小规模应用场景,对于预算有限但又需要可靠存储方案的团队来说,是个很务实的选择。
这篇文章适合谁看?如果你手头正好有一台 Ubuntu 16.04 的机器,需要装 MongoDB 4.2 社区版,又不想被网上那些零散的、版本对不上的教程带偏,那这篇内容就是给你准备的。我会从系统准备、软件源配置、安装步骤、参数调优、常见报错排查这几个维度,把整个流程拆开揉碎讲清楚。中间会穿插一些我实际踩过的坑和验证过的技巧,尽量让你少走弯路。
需要提前说明的是,Ubuntu 16.04 默认的软件源里带的 MongoDB 版本非常老,通常是 2.6 或者 3.x 早期版本,直接apt install mongodb装出来的东西跟 4.2 完全不是一回事。所以我们必须手动添加 MongoDB 官方维护的软件源,才能拿到 4.2 的包。这个思路跟装其他第三方软件是一样的:系统自带的版本太旧,就去官方仓库找新的。
另外,Ubuntu 16.04 的底层库版本比较低,比如 OpenSSL 是 1.0.2 系列,而 MongoDB 4.2 对 OpenSSL 有最低版本要求。这就意味着安装过程中可能会遇到依赖冲突,需要额外处理。这些细节我都会在下面展开。
2. 安装前的系统准备与依赖检查
2.1 确认系统版本和架构
动手之前,先确认你面对的是什么环境。执行下面两条命令:
lsb_release -a uname -m第一条会输出系统的发行版信息,你应该看到Ubuntu 16.04.x LTS这样的字样。第二条看架构,x86_64表示 64 位系统,MongoDB 4.2 只提供 64 位版本,32 位系统就别想了,官方早就不支持了。
注意:如果你看到的是
i686或者i386,说明是 32 位系统,MongoDB 4.2 无法安装。这种情况下要么换机器,要么降级使用更老的 MongoDB 版本,但那些版本早已停止维护,安全风险很高,不建议在生产环境使用。
2.2 更新系统包索引
不管装什么软件,第一步永远是更新包索引:
sudo apt-get update sudo apt-get upgrade -y这一步会把系统里已有的软件包升级到当前源里的最新版本。有人可能会问,为什么装 MongoDB 之前要升级整个系统?原因很简单:MongoDB 4.2 依赖一些系统库,如果这些库版本太旧,安装时会出现依赖不满足的错误。提前升级可以避免很多麻烦。
不过要注意,apt-get upgrade在 Ubuntu 16.04 上可能会升级内核,如果你的机器有特殊的内核模块依赖,升级前最好确认一下。测试环境无所谓,生产环境建议先做快照。
2.3 安装必要的工具包
MongoDB 的安装过程需要用到gnupg和curl或者wget,这些工具在最小化安装的 Ubuntu 16.04 上可能不存在:
sudo apt-get install -y gnupg curl wgetgnupg用来导入 MongoDB 的签名密钥,curl和wget用来下载文件。这三个工具都很小,装上不占地方,但少了任何一个都可能导致后续步骤卡住。
2.4 检查 OpenSSL 版本
前面提到过,MongoDB 4.2 对 OpenSSL 有要求。执行:
openssl versionUbuntu 16.04 默认带的是 OpenSSL 1.0.2g 或更高的小版本。MongoDB 4.2 官方要求 OpenSSL 1.0.1 以上,所以 16.04 自带的版本是满足最低要求的。但如果你之前手动编译过 OpenSSL,或者系统被改过,就要确认一下版本号。低于 1.0.1 的话,MongoDB 启动时会直接报错退出。
2.5 关闭可能冲突的服务
有些 Ubuntu 16.04 的镜像里预装了老版本的 MongoDB,或者有其他服务占用了 27017 端口。先检查一下:
sudo systemctl status mongodb sudo lsof -i :27017如果发现已经有 MongoDB 在跑,先停掉并卸载:
sudo systemctl stop mongodb sudo apt-get remove --purge -y mongodb mongodb-* sudo rm -rf /var/lib/mongodb /var/log/mongodb这一步很关键。老版本的配置文件和数据目录如果残留,新版本启动时可能会读取到不兼容的配置,导致各种奇怪的错误。彻底清理干净再装,能省掉后面很多排查时间。
3. 配置 MongoDB 4.2 官方软件源
3.1 导入 MongoDB 签名密钥
MongoDB 的软件包是用 GPG 密钥签名的,apt 需要这个密钥来验证包的完整性。执行:
wget -qO - https://www.mongodb.org/static/pgp/server-4.2.asc | sudo apt-key add -这条命令从 MongoDB 官网下载 4.2 版本的签名密钥,并添加到系统的 apt 密钥环里。如果网络环境访问官网比较慢,可以多试几次,或者换用curl:
curl -fsSL https://www.mongodb.org/static/pgp/server-4.2.asc | sudo apt-key add -执行成功后,终端会输出OK。如果输出的是gpg: no valid OpenPGP data found,说明下载的内容不对,可能是网络问题导致下载到了错误页面,检查一下网络连通性。
3.2 添加软件源列表
接下来把 MongoDB 4.2 的软件源地址写入 apt 的源列表:
echo "deb [ arch=amd64 ] https://repo.mongodb.org/apt/ubuntu xenial/mongodb-org/4.2 multiverse" | sudo tee /etc/apt/sources.list.d/mongodb-org-4.2.list这里有几个关键点需要解释。xenial是 Ubuntu 16.04 的代号,MongoDB 官方为这个代号维护了 4.2 的软件包。arch=amd64限定了只下载 64 位包,避免 apt 去尝试不存在的 32 位版本。multiverse是 Ubuntu 的软件仓库组件之一,MongoDB 的包放在这个组件下。
提示:如果你用的是 Ubuntu 16.04 的衍生版本,比如某些基于 16.04 的定制系统,代号可能不是
xenial。用lsb_release -c确认一下代号,如果不是xenial,需要把源地址里的代号改成对应的值。但 MongoDB 官方只为标准 Ubuntu 代号维护包,衍生版本可能找不到对应的源。
3.3 刷新包索引并验证源可用性
添加完源之后,刷新一下:
sudo apt-get update如果一切正常,你会看到 apt 从repo.mongodb.org拉取索引信息。如果报错The following signatures couldn't be verified,说明密钥没导入成功,回到 3.1 重新操作。如果报错404 Not Found,说明源地址写错了,检查代号和版本号。
验证一下 apt 能不能找到 MongoDB 4.2 的包:
apt-cache policy mongodb-org输出里应该能看到Candidate: 4.2.x这样的版本号。如果 Candidate 显示的是其他版本,或者根本没有输出,说明源配置有问题。
4. 安装 MongoDB 4.2 及核心组件拆解
4.1 执行安装命令
源配置好了,安装本身其实很简单:
sudo apt-get install -y mongodb-org这个命令会安装一组包,而不是单个包。MongoDB 官方把不同的功能拆成了独立的包,方便按需安装。默认情况下mongodb-org会拉取以下四个组件:
| 包名 | 作用 | 是否必须 |
|---|---|---|
| mongodb-org-server | 数据库服务端主程序 | 是 |
| mongodb-org-mongos | 分片集群路由进程 | 单机不需要 |
| mongodb-org-shell | 命令行客户端 mongo shell | 建议安装 |
| mongodb-org-tools | 备份恢复导入导出工具集 | 建议安装 |
如果你只需要单机数据库,可以只装 server 和 shell:
sudo apt-get install -y mongodb-org-server mongodb-org-shell但我的建议是直接装mongodb-org,因为 tools 里的mongodump、mongorestore、mongoexport、mongoimport这些工具在实际运维中太常用了,少了它们后面还得补装。
4.2 安装过程中的依赖问题处理
在 Ubuntu 16.04 上安装时,可能会遇到依赖错误,最常见的是libcurl3和libssl1.0.0的版本冲突。MongoDB 4.2 的包依赖libcurl3,但系统里可能已经装了libcurl4,两者不能共存。
如果 apt 报错提示依赖不满足,先看看具体缺什么:
sudo apt-get install -f这个命令会尝试自动修复依赖关系。如果修复不了,可能需要手动处理。比如libcurl3和libcurl4冲突时,可以看看是哪个已安装的软件依赖libcurl4,评估一下能不能替换。
注意:不要强行用
dpkg --force安装,那样装出来的 MongoDB 运行时大概率会崩溃。依赖问题要正面解决,不能绕过。
4.3 验证安装结果
安装完成后,确认一下版本:
mongod --version mongo --versionmongod是服务端进程,mongo是客户端 shell。两个命令都应该输出db version v4.2.x这样的信息。如果mongod命令找不到,说明 server 包没装上;如果mongo找不到,说明 shell 包没装上。
再检查一下安装位置:
which mongod which mongo默认情况下,可执行文件在/usr/bin/下,配置文件在/etc/mongod.conf,数据目录在/var/lib/mongodb,日志目录在/var/log/mongodb。这些路径在后续配置和排查时都会用到。
5. 服务管理与关键配置调优
5.1 启动 MongoDB 服务
Ubuntu 16.04 用的是 systemd 管理服务,MongoDB 安装时会自动注册一个mongod服务:
sudo systemctl start mongod sudo systemctl status mongodstatus命令会显示服务当前状态。如果看到active (running),说明启动成功。如果看到failed,就要看日志排查了。
设置开机自启:
sudo systemctl enable mongod这一步很重要,否则服务器重启后 MongoDB 不会自动起来,业务就断了。
5.2 核心配置文件解析
MongoDB 的主配置文件是/etc/mongod.conf,用 YAML 格式写的。安装后的默认配置比较保守,有几个地方值得根据实际情况调整。先看看默认内容:
cat /etc/mongod.conf默认配置大概长这样:
storage: dbPath: /var/lib/mongodb journal: enabled: true systemLog: destination: file logAppend: true path: /var/log/mongodb/mongod.log net: port: 27017 bindIp: 127.0.0.1storage.dbPath是数据文件存放位置。默认在/var/lib/mongodb,如果这个分区空间不够,可以改到更大的分区。改之前要确保新目录存在且 mongodb 用户有读写权限:
sudo mkdir -p /data/mongodb sudo chown -R mongodb:mongodb /data/mongodb然后把dbPath改成/data/mongodb。
net.bindIp默认是127.0.0.1,意味着只有本机能连。如果需要远程访问,要改成0.0.0.0或者具体的网卡 IP。但直接暴露到公网非常危险,一定要配合防火墙和认证机制。
net.port默认 27017,如果这个端口被占用或者有安全策略要求,可以改。改完之后客户端连接也要用新端口。
5.3 内存与并发参数调优
MongoDB 4.2 默认会使用 WiredTiger 存储引擎。WiredTiger 有个特点:它会尽量利用系统内存做缓存。默认情况下,缓存大小是(系统内存 - 1GB) / 2。比如 8GB 内存的机器,缓存大约 3.5GB。
如果你的机器上还跑着其他吃内存的服务,可以手动限制 WiredTiger 缓存:
storage: wiredTiger: engineConfig: cacheSizeGB: 2这个值不是越大越好。设得太大会导致系统内存不足,触发 OOM Killer 把 mongod 进程杀掉;设得太小又会影响查询性能。一般建议留出足够内存给操作系统和其他进程,MongoDB 缓存占物理内存的 50% 到 60% 比较合适。
另外,operationProfiling可以开启慢查询日志,对排查性能问题很有帮助:
operationProfiling: mode: slowOp slowOpThresholdMs: 100这样超过 100 毫秒的操作都会被记录到日志里。生产环境建议开启,但要注意日志量,太频繁的慢查询会快速消耗磁盘空间。
5.4 修改配置后的重启流程
改完配置文件后,需要重启服务才能生效:
sudo systemctl restart mongod sudo systemctl status mongod重启后确认服务正常,然后连上去看看配置有没有生效:
mongo --eval "db.adminCommand({getCmdLineOpts: 1})"这个命令会输出当前生效的启动参数,可以核对一下你改的配置有没有被正确加载。
注意:修改
dbPath后如果服务起不来,大概率是权限问题。MongoDB 以mongodb用户运行,新目录必须让这个用户有读写权限。用ls -la检查目录属主,用chown修正。
6. 安全加固与用户权限体系
6.1 为什么必须开启认证
MongoDB 默认安装后是不需要密码就能连的,任何能访问 27017 端口的人都可以读写所有数据库。这在测试环境可能无所谓,但在任何有外部访问可能的场景下都是灾难。开启认证是安全加固的第一步。
6.2 创建管理员用户
开启认证之前,先要有一个管理员账号。连上 MongoDB:
mongo切换到 admin 数据库,创建超级用户:
use admin db.createUser({ user: "siteAdmin", pwd: "换成你的强密码", roles: [ { role: "userAdminAnyDatabase", db: "admin" }, "readWriteAnyDatabase" ] })userAdminAnyDatabase允许管理所有数据库的用户,readWriteAnyDatabase允许读写所有数据库。这两个角色组合起来基本就是超级管理员了。密码一定要用强密码,不要用123456这种。
6.3 开启认证并验证
编辑/etc/mongod.conf,加上:
security: authorization: enabled重启服务:
sudo systemctl restart mongod然后尝试不带认证连接:
mongo这时候执行show dbs应该会报错not authorized。用管理员账号连接:
mongo -u siteAdmin -p --authenticationDatabase admin输入密码后就能正常操作了。
6.4 为业务创建独立用户
不要用管理员账号跑业务。为每个应用创建独立的数据库和用户:
use appdb db.createUser({ user: "appuser", pwd: "另一个强密码", roles: [ { role: "readWrite", db: "appdb" } ] })这样应用只能访问自己的数据库,即使密码泄露,影响范围也有限。这是最小权限原则的实践。
7. 常见报错与排查技巧实录
7.1 服务启动失败排查思路
MongoDB 启动失败时,systemctl status mongod只会显示一个笼统的failed,具体原因要看日志:
sudo tail -100 /var/log/mongodb/mongod.log日志里通常会有明确的错误信息。下面整理几个我实际遇到过的典型问题:
| 报错信息 | 原因 | 解决方法 |
|---|---|---|
Permission denied | 数据目录权限不对 | chown -R mongodb:mongodb /var/lib/mongodb |
Address already in use | 27017 端口被占用 | lsof -i :27017找到进程并处理 |
Unsupported file format | 数据目录里有旧版本数据 | 清空数据目录或升级数据文件 |
libssl.so not found | OpenSSL 版本不匹配 | 安装兼容的 OpenSSL 版本 |
Too many open files | 文件描述符限制太低 | 调整ulimit和 systemd 限制 |
7.2 连接被拒绝的几种情况
客户端连不上 MongoDB,报Connection refused,可能的原因有:
- MongoDB 服务没启动。用
systemctl status mongod确认。 bindIp只绑定了127.0.0.1,远程连不上。改配置或通过 SSH 隧道连接。- 防火墙拦了 27017 端口。检查
iptables或ufw规则。 - 端口被改过,客户端还在用默认端口。
排查顺序建议从服务状态开始,然后看监听地址,最后查网络和防火墙。
7.3 认证失败的处理
开启认证后,如果报Authentication failed,检查这几点:
- 用户名和密码是否正确,注意大小写。
--authenticationDatabase是否指定了用户所在的数据库。用户是在 admin 库创建的,就要指定 admin。- 用户角色是否有权限访问目标数据库。
有个容易忽略的点:MongoDB 的用户是跟数据库绑定的。在 admin 库创建的用户,认证时必须在 admin 库认证,即使它有权访问其他库。
7.4 磁盘空间不足的预警
MongoDB 数据增长很快,尤其是开启了 journal 和 oplog 的情况下。定期检查磁盘:
df -h /var/lib/mongodb如果空间紧张,可以考虑:
- 清理旧的日志文件,配置 logrotate。
- 检查是否有不需要的集合,用
db.collection.drop()删除。 - 如果用了副本集,oplog 大小可以调整,但需要重启。
提示:不要手动删除数据目录里的文件,那样会破坏数据库一致性。要清理数据,用 MongoDB 提供的命令或者
mongodump备份后重建。
8. 备份恢复与日常运维要点
8.1 逻辑备份与恢复
MongoDB 自带的mongodump和mongorestore是最常用的备份工具。备份整个实例:
mongodump --host 127.0.0.1 --port 27017 -u siteAdmin -p --authenticationDatabase admin --out /backup/mongo-$(date +%Y%m%d)这个命令会把所有数据库导出到指定目录,每个数据库一个子目录,每个集合一个 bson 文件。恢复的时候:
mongorestore --host 127.0.0.1 --port 27017 -u siteAdmin -p --authenticationDatabase admin /backup/mongo-20240101mongodump的优点是简单、跨版本兼容性好,缺点是备份和恢复速度慢,大数据量时不太适用。对于几百 GB 以上的数据,建议用文件系统快照或者 MongoDB 的物理备份方案。
8.2 日常监控指标
运维 MongoDB 要关注几个核心指标:
- 连接数:
db.serverStatus().connections,连接数暴涨可能是应用没正确释放连接。 - 内存使用:
db.serverStatus().mem,关注 resident 和 virtual 的变化。 - 操作计数器:
db.serverStatus().opcounters,query、insert、update、delete 的频率。 - 慢查询:开启 profiling 后,
db.system.profile里能看到慢操作详情。
可以写个简单的脚本定期采集这些指标,或者接入现有的监控系统。
8.3 日志轮转配置
MongoDB 的日志默认会一直追加,时间长了文件会很大。配置 logrotate:
sudo vim /etc/logrotate.d/mongodb内容:
/var/log/mongodb/mongod.log { daily rotate 7 compress delaycompress missingok notifempty create 640 mongodb mongodb }这样每天轮转一次,保留 7 天,自动压缩旧日志。配置完后可以用logrotate -d测试一下。
9. 我踩过的几个坑和最后的小建议
第一个坑是数据目录权限。有次我把 dbPath 改到一个新挂载的磁盘,目录建好了但忘了改属主,MongoDB 启动直接失败,日志里就一句Permission denied,排查了半天才想到是权限问题。后来养成了习惯:改 dbPath 之后第一件事就是chown -R mongodb:mongodb。
第二个坑是OpenSSL 版本冲突。有台机器之前手动编译过 OpenSSL 1.1,系统里同时存在 1.0 和 1.1 两个版本,MongoDB 4.2 链接的是 1.0 的库,但运行时加载到了 1.1,导致启动崩溃。解决办法是用ldd检查 mongod 依赖的库路径,确保它加载的是正确的版本。
第三个坑是认证开启顺序。有次我先在配置里开了authorization: enabled,然后才想起来还没创建管理员用户,结果重启后连不上,只能临时把认证关掉,创建用户后再开。正确的顺序一定是:先创建管理员用户,再开启认证。
最后分享一个小技巧:如果你只是临时测试,不想让 MongoDB 开机自启,可以用sudo systemctl disable mongod。需要的时候手动start,用完stop。这样能省点系统资源,也避免测试数据一直占着端口。
这个环境搭好之后,后续还可以做很多扩展,比如配置副本集实现高可用、搭建分片集群应对海量数据、接入 BI 工具做数据分析。但那是另一个话题了,先把单机跑稳,再考虑这些。