计划
PLAN

MongoDB 4.2 升级到 5.0 技术方案

基于 MongoDB 官方升级文档与当前 Java/Maven 代码静态扫描,梳理升级路径、兼容变化、项目代码改造点、运维步骤、测试清单和风险评估。

2026-05-29-mongodb-50-upgrade.md 2026-05-29 ~19 分钟阅读

1. 背景与结论

flowchart LR
  A[MongoDB 4.2] --> B[MongoDB 4.4]
  B --> C[FCV 4.4]
  C --> D[MongoDB 5.0]
  D --> E[FCV 5.0]
  E --> F[Burn-in 与回归]
MongoDB 必须按 4.2 → 4.4 → 5.0 逐跳升级,并分阶段推进 featureCompatibilityVersion。
要点

不能直接从 MongoDB 4.2 升到 5.0;短期升级应采用 4.2 → 4.4 → 5.0,先控制 FCV 与 legacy UUID 风险,再规划中长期 STANDARD UUID 数据治理。

系统计划将 MongoDB 从 4.2 升级到 5.0。本方案基于 MongoDB 官方升级文档与当前 Java/Maven 代码静态扫描,梳理升级路径、breaking/compatibility changes、项目代码改造点、运维升级步骤、测试验证清单和风险评估。

核心结论:

1

不能直接从 MongoDB 4.2 升到 5.0

。官方要求路径为 4.2 → 4.4 → 5.0

2

featureCompatibilityVersion 必须分阶段推进

4.2 → 4.4 → 5.0,每次设置 FCV 前应先 burn-in 验证。

3

本项目当前 MongoDB Java 客户端依赖已经较新

  1. 因此本次升级的主要风险不是驱动版本不兼容,而是:

2. 官方升级要求与兼容性变化

2.1 升级路径

官方要求:

MongoDB 4.2 → MongoDB 4.4 → MongoDB 5.0
FCV 4.2     → FCV 4.4     → FCV 5.0

推荐节奏:

1

当前 4.2 集群确认稳定,FCV 为 4.2

2

升级二进制到 4.4 最新 patch。

3

保持 FCV 4.2 burn-in 一段时间。

4

稳定后执行

db.adminCommand({ setFeatureCompatibilityVersion: "4.4" })
1

确认 4.4 + FCV 4.4 稳定。

2

升级二进制到 5.0 最新 patch。

3

保持 FCV 4.4 burn-in 一段时间。

4

稳定后执行

db.adminCommand({ setFeatureCompatibilityVersion: "5.0" })

2.2 MongoDB 5.0 重点 compatibility changes

类别MongoDB 5.0 变化对系统影响
Shelllegacy mongo shell 在 5.0 deprecated,推荐 mongosh外部运维脚本、CI、手工 runbook 如果用 mongo,需要迁移或验证
命令参数很多命令遇到未知参数从“忽略”变成“报错”低层 driver command / 运维脚本要排查
TTL 索引expireAfterSeconds: NaN 在 5.0.0-5.0.13 可能被当作 0,导致数据立即过期必须查线上索引元数据,源码里没看到 TTL 定义不代表库里没有
Write Concern5.0 默认 write concern 大多变为 { w: "majority" },有 arbiter 时有例外可能影响写入延迟/可靠性预期;需要 DBA 确认拓扑
Update 顺序update operator 处理字段顺序变化:字符串字段按字典序,数字字段按数字序如果有同一次 update 内 order-sensitive / 冲突字段,需排查
GeogeoHaystack 移除如果线上存在该索引,FCV 5.0 后有风险
Replica Set 配置replSetInitiate / replSetReconfig 对 IP host 配置更严格,推荐 hostname不能仅看应用 URI,要查 rs.conf()
mapReduce5.0 deprecated mapReduce,官方建议改 aggregation本项目源码没发现 mapReduce 调用,但外部脚本仍需查
Aggregationpipeline 最多 1000 stages,部分 stage/事务/readConcern 限制本项目有聚合,建议 5.0 staging 回归

2.3 MongoDB 4.4 中间版本兼容性变化

因为 4.2 必须先升到 4.4,所以也需要关注 4.4 的兼容变化:

类别MongoDB 4.4 变化对系统影响
Removed commandscloneCollection、部分 plan cache 命令移除外部脚本如使用需改造
Projectionfind() / findAndModify() projection 规则变化,path collision 更严格复杂 projection 需要回归
Sortcursor.sort() 与 aggregation $sort 行为更一致,重复值排序稳定性可能变化排序结果如依赖重复值顺序,需加 _id tie-breaker
mapReducereduce 调用、输出字段等行为变化源码未发现 mapReduce,但外部脚本仍需查
Structured loggingmongod/mongos 日志变为结构化 JSON日志采集/解析规则可能要调整
listIndexes不再返回 ns 字段外部索引检查脚本如依赖 ns 需改造

3. 当前项目 MongoDB 使用现状

3.1 Maven 依赖

项目父 POM:

MongoDB starter:

已验证依赖树:

org.springframework.boot:spring-boot-starter-data-mongodb:3.4.3
org.springframework.data:spring-data-mongodb:4.4.3
org.mongodb:mongodb-driver-sync:5.2.1
org.mongodb:mongodb-driver-core:5.2.1
org.mongodb:bson:5.2.1

判断:

3.2 统一 Mongo 配置

主 MongoTemplate 配置:

统一 MongoClientSettings:

关键配置:

MongoClientSettings settings = MongoClientSettings.builder()
        .uuidRepresentation(UuidRepresentation.STANDARD)
        .applyConnectionString(new ConnectionString(getUri()))
        .build();

同时配置了:

3.3 Mongo URI 配置

主 Mongo:

spring:
  data:
    mongodb:
      uri: ${mongodb.uri}

SMS Mongo:

mongodb-sms:
  dbname: journey_sms
  uri: ${mongodb-sms.uri}

另有 request-record 相关 Mongo 配置位于 application 配置后部。

判断:


4. 代码改造点

4.1 高优先级:统一 UUID 编码策略

统一配置使用:

但 questionnaire 模块存在手工 legacy UUID 编解码:

示例:

byte[] bytes = UuidHelper.encodeUuidToBinary(UUID.fromString(strId + ""), UuidRepresentation.JAVA_LEGACY);
Binary binary = new Binary(UUID_LEGACY, bytes);

风险:

建议方案:

方案 A:保留 legacy 数据,封装 legacy UUID 工具

适用条件:

改造内容:

1

新增统一工具类,例如 LegacyUuidBinaryUtils

2

questionnaire 中所有 UuidHelper + UUID_LEGACY 逻辑集中到工具类。

3

读写路径都显式说明 legacy UUID 语义。

4

增加单元测试覆盖 legacy UUID 转换。

优点:

缺点:

方案 B:迁移 legacy UUID 到 STANDARD UUID

适用条件:

改造内容:

1

先扫描 questionnaire 相关集合,统计 _id 和外键字段 BSON binary subtype。

2

编写迁移脚本,将 legacy UUID binary 转为 standard UUID binary。

3

修改 questionnaire 代码,去掉 JAVA_LEGACY / UUID_LEGACY

4

迁移前后做数据量、抽样查询、删除链路验证。

优点:

缺点:

推荐:

4.2 高优先级:统一直接 MongoClient 创建方式

发现部分代码绕过统一配置,直接:

MongoClients.create(uri)

典型位置:

风险:

建议改造:

1

新增统一 MongoClientFactory 或配置 Bean。

2

所有 MongoClients.create(String) 统一收敛。

3

至少统一以下参数

  1. 对不能纳入 Spring 容器的迁移脚本,提供公共静态构造方法或内部工具类。

4.3 中优先级:动态建索引逻辑改造

典型位置:

当前模式:

long count = mongoCollection.countDocuments();
if (count == 0) {
    IndexOptions options = new IndexOptions();
    options.background(true);
    mongoCollection.createIndex(...);
}

问题:

1

countDocuments() == 0 不能可靠代表索引不存在。

2

首次写入时动态建索引,升级/回滚/高并发时容易放大风险。

3

background(true) 在新版本 MongoDB 中已经不是旧语义,不建议继续依赖。

建议改造:

4.4 中优先级:原生 BSON / 手写聚合回归

发现以下模式:

典型位置:

判断:

建议:

  1. 对核心聚合路径在 MongoDB 5.0 staging 环境重放验证。
  2. 比较升级前后:
  1. 中长期逐步替换为:

4.5 中优先级:配置项显式化

建议在 Mongo URI 或统一 settings 中明确以下参数:

注意:


5. 线上元数据检查清单

源码静态扫描没有发现以下问题,但线上必须检查。

5.1 检查 FCV

db.adminCommand({ getParameter: 1, featureCompatibilityVersion: 1 })

预期:

5.2 检查 TTL NaN 索引

db.getCollectionNames().forEach(function (coll) {
  db.getCollection(coll).getIndexes().forEach(function (idx) {
    if (Object.is(idx.expireAfterSeconds, NaN)) {
      print(db.getName() + "." + coll + " has NaN TTL index: " + tojson(idx));
    }
  });
});

处理策略:

5.3 检查 geoHaystack 索引

db.getCollectionNames().forEach(function (coll) {
  db.getCollection(coll).getIndexes().forEach(function (idx) {
    if (idx.key && Object.values(idx.key).includes("geoHaystack")) {
      print(db.getName() + "." + coll + " has geoHaystack index: " + tojson(idx));
    }
  });
});

处理策略:

5.4 检查 replica set host 配置

rs.conf()

重点检查:

5.5 检查默认读写关注

db.adminCommand({ getDefaultRWConcern: 1 })

重点检查:

5.6 检查 mapReduce / server-side JS

源码未发现 mapReduce,但外部脚本和线上任务仍需检查:


6. 运维升级步骤

6.1 升级前准备

  1. 确认拓扑:standalone / replica set / sharded cluster。
  2. 确认当前版本:
db.version()
  1. 确认 FCV:
db.adminCommand({ getParameter: 1, featureCompatibilityVersion: 1 })
1

完整备份。

2

检查 TTL NaN、geoHaystack、rs.conf、default RW concern。

3

检查所有外部脚本是否使用 legacy mongo shell。

4

准备 rollback 方案。

5

准备 staging 回归环境。

6.2 Replica Set:4.2 → 4.4

1

确认所有节点为 4.2,FCV 为 4.2。

2

确认无节点处于 ROLLBACK / RECOVERING

3

逐个升级 secondary

  1. primary step down:
rs.stepDown()
1

升级原 primary。

2

burn-in 验证。

3

稳定后设置 FCV

db.adminCommand({ setFeatureCompatibilityVersion: "4.4" })

6.3 Replica Set:4.4 → 5.0

1

确认所有节点为 4.4,FCV 为 4.4。

2

再次检查 TTL NaN 等元数据。

3

逐个升级 secondary 到 5.0。

4

primary step down。

5

升级原 primary。

6

保持 FCV 4.4 burn-in。

7

应用回归通过后设置 FCV

db.adminCommand({ setFeatureCompatibilityVersion: "5.0" })

6.4 Sharded Cluster 顺序

如为 sharded cluster,顺序为:

1

Disable balancer。

2

升级 config servers。

3

升级每个 shard replica set。

4

升级 mongos。

5

Re-enable balancer。

6

burn-in。

7

设置 FCV。

注意:


7. 测试验证清单

7.1 构建与依赖验证

mvn -f /Users/jack/IdeaProjects/dmtx/biz-projects/pom.xml \
  -pl biz-common \
  -DskipTests \
  dependency:tree \
  -Dincludes=org.springframework.data:spring-data-mongodb,org.mongodb:mongodb-driver-sync,org.mongodb:mongodb-driver-core,org.mongodb:bson

预期:

7.2 代码扫描验证

rg -n "UUID_LEGACY|UuidHelper|UuidRepresentation|JAVA_LEGACY" /Users/jack/IdeaProjects/dmtx/biz-projects
rg -n "MongoClients\.create|getCollection\(|countDocuments\(|insertOne\(|updateOne\(|createIndex\(" /Users/jack/IdeaProjects/dmtx/biz-projects
rg -n "aggregate\(|newAggregation|Aggregation\.|allowDiskUse\(" /Users/jack/IdeaProjects/dmtx/biz-projects
rg -n "mapReduce|expireAfterSeconds|geoHaystack|ensureIndex|copyTo\(|db\.eval" /Users/jack/IdeaProjects/dmtx/biz-projects

7.3 业务回归范围

模块回归内容重点风险
questionnaire表单提交记录查询、删除、导出legacy UUID 读写兼容
whatsapptemplate log 写入、索引创建、统计查询动态表、动态索引、字符串日期
etlHuawei sync / request-record 聚合side MongoClient、手写 pipeline
rtjourney日志写入、报表聚合aggregation 行为和性能
journeyMongoRepository CRUDSpring Data 映射
wechatTaskLog repository CRUDDate / String id 映射
scrmiemail recycle / export 相关 Mongo 逻辑side database 连接配置

7.4 数据一致性验证

升级前后对比:

1

核心集合文档数。

2

questionnaire 指定 UUID 记录能否查询、删除。

3

WhatsApp / Zendesk 统计结果是否一致。

4

ETL 聚合结果是否一致。

5

查询耗时 P95 / P99 是否显著变化。

6

MongoDB slow query 日志是否增加。

7

应用错误日志是否出现 codec / BSON / command parameter 异常。

7.5 性能验证

建议对以下路径做压测或至少批量回放:

关注指标:


8. 风险评估

风险严重级别可能性说明应对策略
直接 4.2 → 5.0官方不支持直接跳升严格执行 4.2 → 4.4 → 5.0
FCV 过早设置 5.0会启用不可向后兼容特性,影响 rollbackbinary 升级后先 burn-in,再设置 FCV
questionnaire UUID 读写不一致STANDARD 与 JAVA_LEGACY 混用明确 UUID 策略,封装或迁移
TTL NaN 导致数据过期低到中源码没看到,但线上索引可能存在升级前查所有索引元数据
side MongoClient 配置不一致中高直接 MongoClients.create 绕过统一配置统一 MongoClientFactory
动态索引创建失败或重复countDocuments 判断不可靠改 listIndexes 或迁移脚本
聚合结果/性能变化Server planner 和行为变化staging 回放、explain 对比
legacy mongo shell 脚本失败5.0 推荐 mongosh外部脚本迁移和验证
write concern 改变导致延迟变化低到中取决于拓扑和 arbiterDBA 查 topology 和 default RW concern
repo 内凭据泄露与升级无直接关系,但影响切换窗口安全迁移到环境变量/密钥管理并轮换

9. 工作量评估

模块工作项预估人天
后端UUID 编码策略确认、封装 legacy UUID 工具或准备迁移方案1.5 - 3
后端统一 MongoClients.create(...) 为公共 factory/config1 - 2
后端动态建索引逻辑改造为 listIndexes 或迁移脚本1 - 2
后端聚合/原生 BSON 查询核心路径回归修复1 - 3
配置梳理所有环境 Mongo URI、补充必要连接参数0.5 - 1
DBA/运维线上元数据检查、备份、升级 runbook、rollback runbook2 - 4
测试MongoDB 5.0 staging 环境业务回归2 - 4
联调应用 + DBA 联合验证、灰度观察1 - 2
合计视是否做 UUID 数据迁移而定10 - 21 人天

如果选择做 legacy UUID 到 STANDARD UUID 的数据迁移,需要额外增加:

模块工作项预估人天
后端/DBA数据扫描脚本、迁移脚本、校验脚本、rollback 脚本3 - 5
测试迁移前后抽样和全量校验2 - 3

10. 推荐执行顺序

Phase 1:升级前整改

1

确认最终生产 MongoDB 5.0 patch 版本。

2

确认 Java driver compatibility。

3

处理 questionnaire UUID 风险。

4

统一 side MongoClient 创建方式。

5

梳理 Mongo URI 配置。

6

准备线上元数据检查脚本。

7

准备 staging MongoDB 5.0 环境。

Phase 2:4.2 → 4.4

1

备份。

2

按 topology 升级 binary。

3

FCV 暂停 4.2 burn-in。

4

应用回归。

5

设置 FCV 4.4。

Phase 3:4.4 → 5.0

1

查 TTL NaN、geoHaystack、rs.conf、default RW concern。

2

按 topology 升级 binary。

3

FCV 暂停 4.4 burn-in。

4

应用完整回归。

5

设置 FCV 5.0。

6

观察 slow query、错误日志、复制延迟、连接池指标。

Phase 4:升级后治理

1

清理 BasicDBObject / DBObject

2

将动态索引创建迁移到标准 migration。

3

推进 UUID STANDARD 化数据迁移。

4

将 repo 内数据库凭据迁移到密钥管理。


11. 官方参考资料


12. 方案质量自检

检查项分数说明
需求理解4/4明确升级目标、验收关注点和约束
竞品/行业实践2/4用户要求只保存上面方案,未继续扩展竞品调研;本方案采用 MongoDB 官方最佳实践作为主要依据
用户/运维体验5/6给出阶段化执行流程、默认 burn-in 策略和检查清单
技术完整度6/6覆盖依赖、配置、代码点、数据兼容、API/driver 行为
可行性4/4给出工作量、风险、执行顺序
附加分2/2对 UUID 保留 legacy 与迁移 STANDARD 给出方案对比

总分: 23 / 26

结论:方案可提交评审。