
一、项目背景与方案选择#
在 MongoDB 兼容数据库的跨云迁移场景中,常见方案主要有两类:
- 基于复制服务的全量 + 增量迁移
- 基于
mongodump/mongorestore的逻辑全量迁移
本文记录的是一次 “华为云 DDS → 天翼云 DDS” 的跨云迁移实践。综合源端与目标端约束、本次数据规模、停机窗口和实施复杂度,最终采用了 基于 mongodump / mongorestore 的逻辑全量迁移方案:
- 在华为云 DDS 源端执行
mongodump --archive --gzip导出 - 在天翼云 DDS 目标端执行
mongorestore --archive --gzip恢复 - 通过集合、索引和关键对象核验迁移结果
该方案的优点是实施简单、操作透明、适合一次性全量切换;需要注意的是,它通常要求停写窗口,不适用于严格零停机迁移。
二、迁移前必须明确的约束#
1. 源端约束:华为云 DDS#
在基于 mongodump / mongorestore 的迁移方式下,源端需重点关注以下边界条件:
- 该方案本质上是全量迁移
- 为保证一致性,迁移前应尽量停止源端业务写入
- 建议在业务低峰期执行导出与切换
- 系统库不应作为迁移对象,不支持迁移系统库
admin和local - 客户端工具版本应与实例版本保持兼容,根据华为云DDS 版本进行工具下载,本次我们迁移的DDS 4.2/4.0版本,用到链接验证工具MongoDB Shell下载对应的版本,MongoDB Command Line Database Tools Download导出导入工具下载对应的版本
此外,在实际执行过程中,如果导出在接近结束时失败,还应优先检查执行主机的磁盘空间是否充足,并预留必要冗余。
2. 目标端约束:天翼云 DDS#
目标端的关键约束同样需要在迁移前确认:
- 不支持高版本向低版本迁移
- 不支持系统库迁移
- 用户和角色需要在目标端手动创建
- 业务对象迁移的核心范围通常为:集合、索引、视图
这意味着,即使源端导出归档中包含了 admin.system.users、admin.system.roles 等系统对象,恢复到目标端时也不应直接恢复系统库内容。目标端所需账号、权限和角色,应通过平台能力或手工方式补齐。
三、迁移环境说明#
1. 源端环境#
本次实操中,源端为华为云 DDS 文档数据库实例,其中本文以 dds-fros 为例进行演示。

使用 mongosh 连接源端:
mongosh "mongodb://127.0.0.1:27017"
mongosh "mongodb://user:password@127.0.0.1:27017/admin"
mongosh --host 127.0.0.1 --port 27017在云数据库环境中,通常可直接使用具备读写权限的迁移账号(比如rwuser用户)连接实例。本文实际连接示例如下:
root@gkfx-sz01p-ecs-uat-his-ecs-dev:~# mongosh "mongodb://rwuser:*******@123.249.113.188:8635/admin?authSource=admin"
Current Mongosh Log ID: 69ea1a7775987a754645bcba
Connecting to: mongodb://<credentials>@123.249.113.188:8635/admin?authSource=admin&directConnection=true&appName=mongosh+1.10.6
Using MongoDB: 4.2.0
Using Mongosh: 1.10.6
mongosh 2.8.2 is available for download: https://www.mongodb.com/try/download/shell
For mongosh info see: https://docs.mongodb.com/mongodb-shell/
[direct: mongos] admin> 查看数据库列表:
[direct: mongos] admin> show dbs
admin 262 B
ccm 257 B
ccm2 27.40 MiB
config 356.12 KiB
dms 419.56 MiB
dms-test 384.22 MiB
form-builder 269 B
freehealth 303.78 KiB
fros 16.24 KiB
fros-test 19.30 KiB
gyyy 262 B
stream 260 B
test 267 B
[direct: mongos] admin> 查看 ccm2 数据库中的集合:
[direct: mongos] admin> use ccm2
switched to db ccm2
[direct: mongos] ccm2> show collections
_Idempotency
_Join:city:Province
_Join:disease:TagDefinition
_Join:diseaseManagement_:Patient
_Join:diseaseManagementDefinition_:Organization
_Join:district:City
_Join:planDefinition:DiseaseManagementDefinition
_Join:role:PractitionerRole
_Join:task:DiseaseManagement
_Role
_SCHEMA
_Session
_User
BasicInfoDefinition
City
CodeableConcept
Disease
DiseaseManagement
DiseaseManagementDefinition
DiseaseManagementIndicator
District
Doctor
Game
Generate_MongoLastResumeData
Generate_PatientObservation
Indicator
IndicatorDefinition
Location
Observation
Organization
Patient
PatientIndicator
PatientIndicatorLog
PlanDefinition
Practitioner
PractitionerRole
Province
Questionnaire
QuestionnaireResponse
RemoteStudy
Report
Reservation
RoleDefinition
Room
Schedule
Sms
Tag
TagDefinition
Task
Test
system.profile
[direct: mongos] ccm2> 为了便于迁移后核验,建议在源端提前记录每个业务库的集合数量。本文使用以下脚本统计各库集合数:
const conn = db.getMongo();
conn.getDBs().databases.forEach(({ name }) => {
const curDb = conn.getDB(name);
const collCount = curDb.getCollectionInfos(
{ type: "collection" },
{ nameOnly: true }
).length;
print(`${name}: ${collCount}`);
});源端统计结果如下:
[direct: mongos] ccm2> use admin
switched to db admin
[direct: mongos] admin> const conn = db.getMongo();
[direct: mongos] admin>
[direct: mongos] admin> conn.getDBs().databases.forEach(({ name }) => {
... const curDb = conn.getDB(name);
... const collCount = curDb.getCollectionInfos(
... { type: "collection" },
... { nameOnly: true }
... ).length;
...
... print(`${name}: ${collCount}`);
... });
admin: 5
ccm: 2
ccm2: 51
config: 14
dms: 53
dms-test: 53
form-builder: 7
freehealth: 3
fros: 11
fros-test: 2
gyyy: 6
stream: 3
test: 5
[direct: mongos] admin> 建议将需要迁移的业务库集合数量提前保存,作为迁移后核验的基础指标。
2. 目标端环境#
目标端为天翼云 DDS 文档数据库实例 GKFX-SZP-DDS-PDT-HIS-dds-fros。本文场景中,目标端启用了 TLS/SSL 连接,因此在客户端侧需要准备服务端证书文件。

注意我们这里目标环境是开启SSL,所以要下载服务端证书,传到客户端进行校验

实际连接目标端的命令如下:
root@gkfx-sz01p-ecs-uat-his-ecs-dev:~# mongosh "mongodb://rwuser:******@10.190.18.168:8635/admin?authSource=admin" --tls --tlsAllowInvalidHostnames --tlsCAFile /root/dds_bak/ca-dds.crt
Current Mongosh Log ID: 69ea102264e5cab4ea53a766
Connecting to: mongodb://<credentials>@10.190.18.168:8635/admin?authSource=admin&directConnection=true&tls=true&tlsAllowInvalidHostnames=true&tlsCAFile=%2Froot%2Fdds_bak%2Fca-dds.crt&appName=mongosh+1.10.6
Using MongoDB: 4.2.0
Using Mongosh: 1.10.6
mongosh 2.8.2 is available for download: https://www.mongodb.com/try/download/shell
For mongosh info see: https://docs.mongodb.com/mongodb-shell/
[direct: mongos] admin> 查看目标端数据库列表:
[direct: mongos] admin> show dbs
admin 262 B
config 38.58 KiB
[direct: mongos] admin> 注意 本文环境中使用了
--tlsAllowInvalidHostnames,原因是服务端证书主机名与实际连接地址不完全匹配。该参数适合临时验证或受控环境排障使用;在正式生产中,更推荐使用与证书一致的域名进行连接,避免长期依赖放宽校验参数。
四、源端导出:执行 mongodump#
1. 导出命令#
本文源端使用 mongodump --archive --gzip 进行整实例逻辑导出。实际执行如下:
root@gkfx-sz01p-ecs-uat-his-ecs-dev:~# mongodump --version
mongodump version: 100.12.2
git version: f76a3ae4029780f61c49cbd39b7336f8d9c30ed0
Go version: go1.23.8
os: linux
arch: amd64
compiler: gc
root@gkfx-sz01p-ecs-uat-his-ecs-dev:~# cd dds_bak/
root@gkfx-sz01p-ecs-uat-his-ecs-dev:~/dds_bak# mongodump --uri="mongodb://rwuser:******@123.249.113.188:8635/?authSource=admin" --archive=dds-fros_full_20260423.gz --gzip >> dds-fros_full_20260423.log 2>&1
该方式的优点是:
- 生成单一归档文件,便于管理
- 配合
--gzip可降低归档体积 - 适合跨环境传输与恢复
2. 导出过程观察#
导出过程中可在另一窗口实时观察日志:
tail -f dds-fros_full_20260423.log日志片段如下:
Last login: Thu Apr 23 20:30:33 2026 from 117.186.13.106
root@gkfx-sz01p-ecs-uat-his-ecs-dev:~# cd dds_bak/
root@gkfx-sz01p-ecs-uat-his-ecs-dev:~/dds_bak# tail -f dds-fros_full_20260423.log
2026-04-23T20:43:20.832+0800 [###########.............] dms.Observation 121742/247927 (49.1%)
2026-04-23T20:43:20.832+0800
2026-04-23T20:43:22.785+0800 [########################] dms-test.Observation 180802/180802 (100.0%)
2026-04-23T20:43:22.889+0800 done dumping dms-test.Observation (180802 documents)
2026-04-23T20:43:22.889+0800 writing ccm2.Indicator to archive 'dds-fros_full_20260423.gz'
2026-04-23T20:43:23.832+0800 [........................] dms.QuestionnaireResponse 5560/247297 (2.2%)
2026-04-23T20:43:23.832+0800 [........................] dms-test.QuestionnaireResponse 5560/181185 (3.1%)
2026-04-23T20:43:23.832+0800 [###########.............] dms.Observation 121742/247927 (49.1%)
2026-04-23T20:43:23.832+0800 [........................] ccm2.Indicator 101/126910 (0.1%)
2026-04-23T20:43:23.832+0800
2026-04-23T20:43:26.832+0800 [........................] dms.QuestionnaireResponse 5560/247297 (2.2%)
2026-04-23T20:43:26.832+0800 [........................] dms-test.QuestionnaireResponse 5560/181185 (3.1%)
2026-04-23T20:43:26.833+0800 [###########.............] dms.Observation 121742/247927 (49.1%)
2026-04-23T20:43:26.833+0800 [........................] ccm2.Indicator 101/126910 (0.1%)
2026-04-23T20:43:26.833+0800
2026-04-23T20:43:29.832+0800 [........................] dms.QuestionnaireResponse 5560/247297 (2.2%)
2026-04-23T20:43:29.832+0800 [........................] dms-test.QuestionnaireResponse 5560/181185 (3.1%)
2026-04-23T20:43:29.832+0800 [###########.............] dms.Observation 121742/247927 (49.1%)
2026-04-23T20:43:29.832+0800 [........................] ccm2.Indicator 101/126910 (0.1%)
2026-04-23T20:43:29.832+0800
^C
root@gkfx-sz01p-ecs-uat-his-ecs-dev:~/dds_bak# 从导出日志可以确认以下事实:
- 源端业务库中的多个集合被持续写入归档文件
- 导出过程能够显示集合级进度与已完成对象
- 日志中还出现了系统对象,如:
admin.system.usersadmin.system.rolesadmin.system.version
这说明本次导出归档中不仅包含业务库数据,也包含了部分系统元数据。
3. 导出结论#
结合导出日志,可以得出以下结论:
- 本次
mongodump导出已正常完成 - dump 归档中包含业务库数据及其相关元数据
- 归档中同时包含系统用户、角色等系统级对象,但这些内容不应在目标端直接恢复
五、目标端恢复:执行 mongorestore#
1. 恢复策略#
由于目标端不支持系统库迁移,同时目标端用户和角色需要手工创建,因此恢复时不能直接整包无选择恢复,而应采用业务库白名单恢复。
本文恢复命令如下:
mongorestore --host 10.190.18.168 --port 8635 --ssl --tlsInsecure --sslCAFile ca-dds.crt --authenticationDatabase admin -u rwuser --password='******' --archive=dds-fros_full_20260423.gz --gzip --nsInclude='ccm.*' --nsInclude='ccm2.*' --nsInclude='dms.*' --nsInclude='dms-test.*' --nsInclude='form-builder.*' --nsInclude='freehealth.*' --nsInclude='fros.*' --nsInclude='fros-test.*' --nsInclude='gyyy.*' --nsInclude='stream.*' --nsInclude='test.*' >> restore_dds_fros_full_20260423.log 2>&1这条命令的核心思路是:
- 使用白名单方式,仅恢复业务库
- 显式排除
admin、config、local等系统库 - 保证恢复对象范围与目标端约束一致
说明 文中的
mongosh连接示例采用了--tls写法,而mongorestore示例中使用了--ssl/--sslCAFile。在实际工具中这类参数通常存在兼容关系,但在正式实施文档中,建议统一工具参数风格,并明确说明证书校验策略。本文保留实操原始命令,以便完整还原执行过程。
2. 恢复过程观察#
恢复过程中可通过以下命令实时查看日志:
tail -f restore_dds_fros_full_20260423.log日志片段如下:
root@gkfx-sz01p-ecs-uat-his-ecs-dev:~/dds_bak# tail -f restore_dds_fros_full_20260423.log
2026-04-23T22:46:37.365+0800 index: &idx.IndexDocument{Options:primitive.M{"background":true, "name":"reqId_1", "ns":"form-builder._Idempotency", "sparse":true, "unique":true, "v":2}, Key:primitive.D{primitive.E{Key:"reqId", Value:1}}, PartialFilterExpression:primitive.D(nil)}
2026-04-23T22:46:37.365+0800 index: &idx.IndexDocument{Options:primitive.M{"background":true, "expireAfterSeconds":0, "name":"ttl", "ns":"form-builder._Idempotency", "sparse":true, "v":2}, Key:primitive.D{primitive.E{Key:"expire", Value:1}}, PartialFilterExpression:primitive.D(nil)}
2026-04-23T22:46:37.366+0800 no indexes to restore for collection gyyy.template
2026-04-23T22:46:37.366+0800 no indexes to restore for collection gyyy.test
2026-04-23T22:46:37.366+0800 restoring indexes for collection gyyy.ehr from metadata
2026-04-23T22:46:37.366+0800 index: &idx.IndexDocument{Options:primitive.M{"background":true, "name":"identifier", "ns":"gyyy.ehr", "unique":true, "v":2}, Key:primitive.D{primitive.E{Key:"identifier", Value:1}}, PartialFilterExpression:primitive.D(nil)}
2026-04-23T22:46:37.378+0800 no indexes to restore for collection gyyy.opt
2026-04-23T22:46:37.378+0800 no indexes to restore for collection gyyy.ethnic
2026-04-23T22:46:37.378+0800 no indexes to restore for collection fros-test.ehr
2026-04-23T22:46:41.113+0800 2431940 document(s) restored successfully. 0 document(s) failed to restore.
^C
root@gkfx-sz01p-ecs-uat-his-ecs-dev:~/dds_bak# 从恢复日志中可以确认:
- 11 个业务库均已纳入恢复范围
- 恢复过程中未观察到失败记录
- 日志明确显示多个集合正在从元数据恢复索引
- 最终恢复统计为:
2431940 document(s) restored successfully0 document(s) failed to restore
这说明本次恢复整体完成情况良好。
3. 关于系统用户与权限#
这里需要明确区分两个层面:
源端归档中是否包含系统用户和角色#
包含。
因为导出日志中已出现:
admin.system.usersadmin.system.rolesadmin.system.version
目标端是否恢复了系统用户和角色#
没有恢复。
原因并非数据缺失,而是恢复策略有意规避了系统库:
- 恢复命令仅对白名单业务库执行
--nsInclude - 恢复日志未显示
admin.system.users、admin.system.roles进入恢复流程 - 目标端本身也不支持直接迁移系统库对象
因此,本次迁移中:
- MongoDB 系统级用户/角色:源端归档中存在,但目标端不恢复
- 业务库中的应用级集合,如
_User、_Role、RoleDefinition等,作为业务数据的一部分被正常恢复
六、迁移结果校验#
恢复完成后,需要从多个维度验证迁移结果,而不仅仅依赖日志结论。
1. 校验数据库是否已恢复#
连接目标端
root@gkfx-sz01p-ecs-uat-his-ecs-dev:~/dds_bak# mongosh "mongodb://rwuser:******@10.190.18.168:8635/admin?authSource=admin" --tls --tlsAllowInvalidHostnames --tlsCAFile /root/dds_bak/ca-dds.crt
Current Mongosh Log ID: 69ea17f42a1c583ab4f5c435
Connecting to: mongodb://<credentials>@10.190.18.168:8635/admin?authSource=admin&directConnection=true&tls=true&tlsAllowInvalidHostnames=true&tlsCAFile=%2Froot%2Fdds_bak%2Fca-dds.crt&appName=mongosh+1.10.6
Using MongoDB: 4.2.0
Using Mongosh: 1.10.6
mongosh 2.8.2 is available for download: https://www.mongodb.com/try/download/shell
For mongosh info see: https://docs.mongodb.com/mongodb-shell/
[direct: mongos] admin> 查看数据库列表:
[direct: mongos] admin> show dbs
admin 262 B
ccm 257 B
ccm2 44.71 MiB
config 38.58 KiB
dms 360.96 MiB
dms-test 154.04 MiB
form-builder 269 B
freehealth 287.84 KiB
fros 16.24 KiB
fros-test 257 B
gyyy 57.63 KiB
stream 260 B
test 267 B
[direct: mongos] admin> 可以看到,目标端业务数据库均已出现。
说明
show dbs中显示的库大小受底层存储、压缩、索引重建和碎片等因素影响。跨环境迁移后,数据库大小不完全一致并不必然表示数据异常。因此,容量只可作为参考指标,不能单独作为一致性结论依据。
2. 校验集合清单是否一致#
以 ccm2 为例:
[direct: mongos] admin> use ccm2
switched to db ccm2
[direct: mongos] ccm2> show collections
_Idempotency
_Join:city:Province
_Join:disease:TagDefinition
_Join:diseaseManagement_:Patient
_Join:diseaseManagementDefinition_:Organization
_Join:district:City
_Join:planDefinition:DiseaseManagementDefinition
_Join:role:PractitionerRole
_Join:task:DiseaseManagement
_Role
_SCHEMA
_Session
_User
BasicInfoDefinition
City
CodeableConcept
Disease
DiseaseManagement
DiseaseManagementDefinition
DiseaseManagementIndicator
District
Doctor
Game
Generate_MongoLastResumeData
Generate_PatientObservation
Indicator
IndicatorDefinition
Location
Observation
Organization
Patient
PatientIndicator
PatientIndicatorLog
PlanDefinition
Practitioner
PractitionerRole
Province
Questionnaire
QuestionnaireResponse
RemoteStudy
Report
Reservation
RoleDefinition
Room
Schedule
Sms
Tag
TagDefinition
Task
Test
system.profile
[direct: mongos] ccm2> 从集合清单看,目标端与源端保持一致。
3. 校验各业务库集合数量#
在目标端再次执行集合统计脚本:
const conn = db.getMongo();
conn.getDBs().databases.forEach(({ name }) => {
const curDb = conn.getDB(name);
const collCount = curDb.getCollectionInfos(
{ type: "collection" },
{ nameOnly: true }
).length;
print(`${name}: ${collCount}`);
});目标端输出结果如下:
[direct: mongos] ccm2> use admin
switched to db admin
[direct: mongos] admin> const conn = db.getMongo();
[direct: mongos] admin>
[direct: mongos] admin> conn.getDBs().databases.forEach(({ name }) => {
... const curDb = conn.getDB(name);
... const collCount = curDb.getCollectionInfos(
... { type: "collection" },
... { nameOnly: true }
... ).length;
...
... print(`${name}: ${collCount}`);
... });const conn = db.getMongo();
admin: 5
ccm: 2
ccm2: 51
config: 14
dms: 53
dms-test: 53
form-builder: 7
freehealth: 3
fros: 11
fros-test: 2
gyyy: 6
stream: 3
test: 5
[direct: mongos] admin> 与源端统计结果一致。
4. 建议补充的深度校验项#
在正式生产切换前,建议进一步增加以下核验动作:
- 对关键集合执行
countDocuments()对比 - 对关键集合索引执行
getIndexes()对比 - 抽样比对关键业务数据,例如按
_id或业务主键检查若干记录 - 对应用侧执行读写验证或关键接口冒烟测试
示例:
use ccm2
db.Patient.countDocuments()
db.Patient.getIndexes()
db.Patient.findOne()这些校验项能够比“仅比较集合数量”提供更强的一致性证明。
七、推荐的标准实施步骤#
综合本次实践,推荐将类似跨云迁移流程标准化为以下步骤:
步骤 1:确认版本与工具兼容性#
- 确认源端与目标端版本兼容
- 确认
mongosh、mongodump、mongorestore版本与实例兼容 - 确认目标端 TLS/SSL 连接要求
步骤 2:确认迁移窗口并停写#
- 选择业务低峰期
- 停止源端业务写入
- 固定切换窗口,避免导出期间继续产生增量
步骤 3:执行源端导出#
- 使用
mongodump --archive --gzip导出 - 实时观察导出日志
- 记录源端数据库、集合数量与关键集合文档数
步骤 4:准备目标端账号与连接能力#
- 提前确认目标端账号权限
- 准备 CA 证书等连接材料
- 若目标端不支持系统库迁移,提前规划账号和角色创建方式
步骤 5:仅恢复业务库#
- 使用
--nsInclude明确业务库白名单 - 避免恢复
admin、config、local - 实时观察恢复日志并确认失败数为 0
步骤 6:执行迁移后核验#
- 核验数据库是否已出现
- 核验集合数量是否一致
- 核验关键集合文档数、索引、抽样数据是否一致
- 验证业务应用连接与核心功能
步骤 7:切换与回退准备#
- 在目标端验证通过后进行应用切换
- 如发现重大差异,保留源端作为回退入口
- 在确认业务稳定前,不要立即销毁源端数据或归档文件
八、最终结论#
结合源端导出日志、目标端恢复日志以及迁移后核验结果,本次 “华为云 DDS → 天翼云 DDS” 的迁移实践可以得出以下结论:
- 方案选择合理
基于
mongodump/mongorestore的逻辑全量迁移,适用于本次存在停写窗口、希望降低迁移成本的跨云迁移场景。 - 源端导出成功 本次导出的归档文件已正常生成,且包含业务库数据及系统级元数据。
- 目标端恢复策略正确
通过
--nsInclude精确恢复业务库,规避了系统库恢复风险,符合目标端约束要求。 - 业务库恢复完成
恢复日志显示全部业务库已纳入恢复范围,且恢复结果为
0 document(s) failed to restore。 - 索引已随恢复流程重建
恢复日志中多次出现
restoring indexes for collection ... from metadata,说明目标端已执行索引恢复。 - 系统用户和角色未恢复到目标端 这是基于目标端限制和恢复策略刻意设计的结果,目标端系统账号与权限需单独创建。
- 迁移结果符合预期 从数据库列表、集合清单、集合数量和恢复日志来看,本次迁移整体成功;在正式切流前,仍建议结合关键集合文档数、索引和业务抽样进一步完成最终验收。
