MongoDB:记一次数据迁移经验

发布于:2025-02-18 ⋅ 阅读:(58) ⋅ 点赞:(0)

目录

任务场景

任务分析

任务过程

mongodump/mongorestore

compass工具

任务总结

技术深入


任务场景

        项目现场因为历史遗留问题,有两套MongoDB数据库架构,且版本不一致。现在需要将一些MongoDB集合从低版本数据库迁移到高版本数据库。项目的详细场景信息如下:

项目情况 项目信息
低版本数据库 3.4.6版本
高版本数据库 5.0.24版本
低版本数据库架构 双分片
高版本数据库架构 三副本
需要迁移的MongoDB集合总数量 25
total_size做大的集合 50G
total_size > 1G的集合数量 5
200M < total_size < 1G的集合数量 4
大集合索引情况 大集合索引数量较多

任务分析

        所谓迁移,其实本质上就是将数据从一个地方完整的放到另一个地方,而且要能用;也就是数据导出、再导入,导入后还要能用。

        MongoDB数据迁移的手段有很多:ETL工具,MongoDB的mongodump/mongorestore、mongoexport/mongoimport、compass工具等。

方法 简要分析说明
ETL工具(kettle)

1、可以创建索引;

2、迁移过程可追溯;

3、集合名称、字段名有开发出错的风险;

4、大集合不适合全量一次性同步,需要分批次增量同步过去;

mongodump/mongorestore

1、迁移会保留索引和元数据;

2、适合全量备份迁移;

3、对于大集合导出导入效率较高;

4、会受限于网络速度

mongoexport/mongoimport

1、导出的文件可以是json、csv,可读性较高;

2、适合小数据量迁移

3、不会保留索引和元数据;

4、迁移效率较低;

compass工具

1、导出的文件可以是json、csv,可读性较高;

2、不需要写命令,不需要开发;

3、适合小数据量迁移;

4、不会保留索引和元数据;

5、迁移效率较低;

        针对此次迁移任务场景,集合数量25个,大集合9个,小集合16个,且大集合索引数量较多,小集合索引很少。

        所以计划分两批去迁移:

(1)针对200M以下的16个小集合,采用compass工具进行迁移;

(2)针对200M以上的9个大集合,采用mongodump/mongorestore工具进行迁移;

        (1)compass工具迁移小集合

        compass的导出导入非常简单,动动手操作下图形界面即可;而且小集合索引较少,手动创建索引也不会耗费太多时间。

        (2)mongodump/mongorestore工具迁移大集合

        大集合迁移要考虑两个问题,导出导入效率、索引创建问题。mongodump/mongorestore对于大集合的迁移效率是非常高的,且可以开启并发参数加快导入导出速度;而且mongodump/mongorestore工具可以自动创建索引,解决了索引多且大的负责问题。

任务过程

        无论是使用何种迁移方式,除非是添加副本成员去同步数据,都需要先将集合对应的业务暂停再进行迁移,否则就有漏数据的风险。

mongodump/mongorestore

        因为项目现场的两套MongoDB数据库的版本及database-tools版本不一致,所以只能先使用mongodump导出集合的二进制bosn文件,然后将文件传输到目标数据库服务器上,最后使用mongorestore进行恢复。这次任务也验证了低版本(3.4.6)的mongodump导出的二进制文件,使用高版本的mongorestore(100.5.2)可以对其进行恢复导入。

1、mongodump导出目标集合

  • mongodump命令直接在Linux的命令行下执行,不可以在mongo-shell中执行
  • 代码块中的 “ \ ” 符号是换行符,避免一行命令写的太长导致可读性变差
  • --uri:数据库的连接字符串,需要严格按照语法格式中给出的例子去写
  • --collection:需要导出的集合
  • --numParallelCollections:开启并发数,开启后可以加快速度,但这个参数比较吃CPU
  • --out:导出的文件的输出路径
//语法格式
mongodump \
  --uri="mongodb://用户名:密码@源IP:27017/mydb" \
  --collection=mycollection \
  --numParallelCollections 4 \
  --out=./mydb_backup

//实际操作
mongodump \
  --uri="mongodb://zqd:123456@192.168.0.34:27017/TEST" \
  --collection=ETL_MODEL\
  --numParallelCollections 4 \
  --out=/mongodb/backup

        mongodump执行成功后,会在备份目录,也就是代码块中的/mongodb/backup目录下生成两份文件:数据文件、元数据文件。数据文件中存储了集合的行数据,元数据文件中包括集合的索引信息、集合选项、其他元信息等,这两份文件都是恢复数据时所必要的。

2、文件传输

        文件导出成功后,需要将文件传输到目标服务器上,可以使用scp命令,这个步骤就比较考验网速了。我在做的时候,50G的文件,传输了20分钟。

scp -r /mongodb/backup/TEST root@192.168.0.202:/mongodb/backup  

3、mongorestore导入目标集合

  • 代码块中的 “ \ ” 符号是换行符,避免一行命令写的太长导致可读性变差
  • --uri:数据库的连接字符串,需要严格按照语法格式中给出的例子去写
  • --collection:需要导入的集合
  • --numParallelCollections:开启并发数,开启后可以加快速度,但这个参数比较吃CPU
  • --drop:若目标集合已存在,先删除旧数据
  • /mongodb/backup/TEST/ETL_MODEL.bson:需导入的bson文件绝对路径
//语法格式
mongorestore \
  --uri="mongodb://用户名:密码@目标IP:27017/mydb" \
  --collection=mycollection \
  --numParallelCollections 4 \
  --drop \  # 可选:若目标集合已存在,先删除旧数据
  /目标路径/mydb_backup/mydb/mycollection.bson

//实际操作
mongorestore \
  --uri="mongodb://zqd:123456@192.168.0.202:27017/TEST" \
  --collection=ETL_MODEL \
  --numParallelCollections 4 \
  --drop /mongodb/backup/TEST/ETL_MODEL.bson

        虽然mongodump导出的文件有数据文件、元数据文件两个,但是在使用mongorestore导入时,只需要指定数据文件即可,mongorestore会自动读取元数据文件信息用来重构索引;这也是为什么元数据文件需要和数据文件在同一目录下。

        下图是成功恢复导入的一个例子:

compass工具

1、compass导出

        描述导出导入过程之前,建议是将需要导出的集合统一全部导出后,放入同一个目录,导入的时候直接来这个目录找文件,这样不容易出错,且效率更高。

        compass选择导出按钮点击,在导出时不要选择“Export Full Collection”;要选择字段进行导出,选择字段时,将_id字段勾选去掉,否则会影响导入。

2、compass导入

选择Import Data即可导入刚刚导出的json或者csv文件。

任务总结

        这次MongoDB数据迁移任务做完,有两个可以提炼出的的经验是

(1)如果需要迁移的集合数量不多,就完全可以手动操作。

(2)对于小集合,手工操作的话,compass工具要比mongoexport/mongoimport效率更高。

(3)对于大集合,手工操作的话,一定要选用mongodump/mongorestore工具

(4)写个shell脚本模板,后续再有类似场景的迁移,只需要改下集合名称的参数值即可,也不必要再手工操作了。

技术深入

        mongodump/mongorestore用于MongoDB数据的迁移是非常高效的,且功能强大,值得再深入探究一下。下面会从其版本变化、下载、配置、直接迁移、导出内容、索引重构、多个集合这几个方面再深入描述一下。

        至于全库备份迁移,这里就不扩展了,因为也不适合本篇文章的讨论方向。而且MongoDB作为分布式数据库,存储一般都是非常大的,动不动都是10个T以上,全库备份和恢复的时间成本都非常高。在不考虑异地备份的前提下,真实的项目上其实很少有真的去做备份和恢复。基本都是三副本架构,坏了一台,立即由其他两台接管,然后再去修复坏掉的那台数据库。

1、版本变化

        mongodump/mongorestore在MongoDB数据库4.4版本之前是在安装部署数据库时自带的工具,但是在4.4版本之后,需要独立安装MongoDB Command Line Database Tools才能使用。

2、工具下载

从MongoDB4.4版本之后,mongodump/mongorestore需要独立安装,其安装包可以从官网下载,下载地址:MongoDB数据库工具下载地址

3、安装配置

        安装很简单,把下载的MongoDB Command Line Database Tools压缩包上传到数据库服务器上,然后解压即可。

         但是解压后,不能立即使用;需要将其bin目录添加到环境变量中(记得修改完source环境变量文件)。

4、直接迁移

        直接迁移的意思是指,不再先导出到本地,不再占用本地存储空间;mongodump/mongorestore可以将集合从源数据库直接迁移到目标数据库

        代码块中的 “ | ” 就类似于迁移的管道,“ | ” 前后的命令与mongodump、mongorestore单独使用时的用法没有差别。

mongodump --uri="mongodb://zqd:123456@192.168.0.34:27017/TESTZQD" --collection=TEST \
| mongorestore --uri="mongodb://zqd:123456@192.168.0.202:27017/TESTZQD" --drop

        但是,这种直接迁移的操作有一个前提条件:需要mongodump/mongorestore的版本一致;这里的一致指的是源数据库服务器上的工具版本和目标数据库服务器版本保持一致。如果不一致的话,可以通过降级或者升级将两方版本更新成一致后,即可进行迁移。

        回顾文章前文的迁移,并没有进行mongodump/mongorestore版本更新。是因为项目环境中的源数据库版本是3.4.6,目标数据库版本是5.0.24,版本跨度太大,尝试后发现无法再进行版本统一。而4.4版本之后的数据库,应该都可以通过使用相同版本的MongoDB Command Line Database Tools进行直接迁移。

5、mongodump导出内容

数据文件

文件以 .bson 结尾,存储集合中的文档(行数据)

元数据文件

文件以 .metadata.json 结尾,存储集合中的配置信息,包括索引信息、集合选项(固定集合大小、验证规则)、其他元信息(UUID、创建时间)

6、重建索引

        使用mongorestore恢复集合时,会在数据文件导入完成后,根据元数据文件中的索引定义,进行索引重建,大的索引重建会比较慢,我的经验是一个集合中有8个索引,共7个G的索引大小,重建耗时20min。

        使用mongorestore恢复集合时,如果想先导入数据再手动创建索引,也可以禁用索引重建。可以在使用mongorestore工具时,加入代码块中参数。但不建议这么做,手工创建索引耗时且麻烦。

mongorestore --noIndexRestore --uri="..." /备份路径

        在重建索引时,需要确保mongorestore的版本高于源数据库版本,因为源数据库版本如果过高,可能会有些新特性,导致旧版本的mongorestore无法识别。

7、mongodump导出多个集合 

        我在使用mongodump做集合导出的时候,就在想一个问题:如果一个个导出,稍显麻烦。但是就几个集合,又懒得写shell脚本。mongodump就不能同时指定多个集合进行导出吗?

        其实还真行,但有版本限制。MongoDB4.4版本以上的数据库,可以通过指定多个--collection参数同时导出多个集合。但是4.4版本以下的数据库,就不支持这样操作了。

        而且还有个操作可以导出多个集合——导出整个数据库。但这个就有点大炮打蚊子的意思了,没必要。