文章目录

  • 介绍
  • 后端技术栈
  • 前端技术栈
  • 功能介绍
  • 模块导航
  • 核心代码介绍
  • 系统开发部署
  • 数据迁移配置项说明
  • 集成开发
  • 系统运行展示
  • 结语


介绍

今天分享一款非常实用的异构数据库迁移工具,可以进行多种常见数据库之间的数据或结构迁移,相比于其他的数据迁移工具,它还支持字段索引,默认值,字段约束的信息同步,mysql 的主键递增等,支持基于正则表达式转换的表名与字段名映射转换。

同步方式分为全量和增量同步两种类型,同步算法借鉴了 kettle 的数据同步算法,支持手动和定时执行。目前支持的数据库类型有 MySQL/MariaDB/Oracle/SQL Server/PostgreSQL/Greenplum/DB2/DMDB/Kingbase8/HighGo/Hive/SQLite,后续会不断开放更多的数据库类型。(源码文档获取方式见文末)

后端技术栈

  • 开发框架:Spring Boot 2.3
  • 微服务框架:Spring Cloud Hoxton.SR9
  • 任务调度:Quartz
  • 持久层框架:MyBatis Plus
  • 数据库连接池:Hikaricp
  • 客户端负载均衡:Ribbon
  • 熔断组件:Hystrix
  • 网关组件:Spring Cloud Gateway
  • 日志管理:Logback

前端技术栈

  • JS框架:Vue、nodejs
  • 组件库:ElementUI
  • 打包构建工具:Webpack

功能介绍

提供源端数据库向目的端数据库的批量迁移同步功能,支持数据的全量和增量方式同步。包括:

  • 结构迁移

支持字段类型、主键信息、建表语句等的转换,并生成建表SQL语句。

支持基于正则表达式转换的表名与字段名映射转换。

支持字段索引,默认值,字段约束的信息同步。

  • 数据同步

基于JDBC的分批次读取源端数据库数据,分批次写入目的数据库。

支持有主键表的增量变更同步,算法借鉴了 kettle 的基于主键的同步算法。

模块导航

middle-service-etl-web – 前端工程[8080]
middle-ground-api – 后端工程
├── middle-common – 系统公共模块
├ ├── middle-core – 公共核心包,控制环境变量
├ ├── middle-db-core – 数据库核心包
├ ├── middle-dbswtich-- 数据库迁移核心组件包
├ ├── middle-http – 网络相关组件包
├── middle-eureka – 注册中心[8610]
├── middle-gateway – Spring Cloud Gateway网关[8082]
├── middle-service-etl-- 数据库迁移业务代码

核心代码介绍

该系统的核心代码是它的数据迁移的相关组件包,位于 middle-common 下的 middle-dbswtich 中,其中 middle.ground.dbswitch.data.service.MigrationService 和middle.ground.dbswitch.data.handler.MigrationHandler 两个类是数据迁移的主要逻辑和算法相关的代码,通过调用 MigrationService 的 run 方法可以启动数据迁移,然后异步调用 MigrationHandler 的 get 方法运行相关逻辑,完成数据迁移。感兴趣的朋友可以自行查阅相关代码,静下心来看就能捋顺其中的逻辑。

系统开发部署

jdk 1.8(特别注意: 在Java9及以上版本默认情况下不允许应用程序查看来自JDK的所有类,但在数据迁移组件中利用反射计算对象的字节大小,所以需要在JVM启动时需要增加如下参数:)

--add-opens java.base/jdk.internal.loader=ALL-UNNAMED --add-opens jdk.zipfs/jdk.nio.zipfs=ALL-UNNAMED

数据库版本为 mysql5.7 及以上版本

导入 db 文件夹下的 sql 脚本middle_service_etl.sql

把系统导入 idea 中,等待 maven 依赖下载完毕

修改 middle-service-etl 模块的 yml 配置文件(配置文件生效配置在 middle-common/middle-core 的 yml 文件中指定),把 mysql 的用户名密码改成自己数据库的用户名和密码

依次执行 middle-eureka 下的 EurekaApplication,middle-gateway 下的 GatewayApplication,middle-service-etl 下的 MiddleServiceEtlApplication

本地安装稳定版 node.js,把 middle-service-etl-web 导入 hbuidx 或 vscode,执行 npm install 命令,然后执行 npm run dev 即可,若运行报错,安装 jsx 依赖,再次执行 npm run dev 即可:

npm install babel-plugin-transform-vue-jsx
npm install babel-helper-vue-jsx-merge-props
npm install babel-plugin-syntax-jsx

访问 http://localhost:8080

数据迁移配置项说明

配置参数

配置说明

示例

备注

dbswitch.source[i].url

来源端JDBC连接的URL

jdbc:oracle:thin:@127.0.0.1:1521:orcl

可为:oracle/mysql/mariadb/sqlserver/postgresql/db2/dm/kingbase8/highgo 等

dbswitch.source[i].driver-class-name

来源端数据库的驱动类名称

oracle.jdbc.driver.OracleDriver

对应数据库的驱动类

dbswitch.source[i].username

来源端连接帐号名

root


dbswitch.source[i].password

来源端连接帐号密码

root


dbswitch.source[i].fetch-size

来源端数据库查询时的fetch_size设置

10000

需要大于100 有效

dbswitch.source[i].source-schema

来源端的schema名称

test

多个之间用英文逗号分隔

dbswitch.source[i].source-includes

来源端schema下的表中需要包含的表名称

users1

支持多个表(多个之间用英文逗号分隔);支持正则表达式(不能含有逗号)

dbswitch.source[i].source-excludes

来源端schema下的表中需要过滤的表名称

users,orgs

不包含的表名称,多个之间用英文逗号分隔

dbswitch.source[i].regex-table-mapper

基于正则表达式的表名称映射关系

[{“from-pattern”: “^”,“to-value”: “T_”}]

为list类型,元素存在顺序关系

dbswitch.source[i].regex-column-mapper

基于正则表达式的字段名映射关系

[{“from-pattern”: “$”,“to-value”: “_x”}]

为list类型,元素存在顺序关系

dbswitch.target.url

目的端JDBC连接的URL

jdbc:postgresql://127.0.0.1:5432/test

可为:oracle/sqlserver/postgresql/greenplum/mysql/mariadb/db2/dm/kingbase8/highgo 等

dbswitch.target.driver-class-name

目的端 数据库的驱动类名称

org.postgresql.Driver

对应数据库的驱动类

dbswitch.target.username

目的端连接帐号名

root


dbswitch.target.password

目的端连接帐号密码

root


dbswitch.target.target-schema

目的端的schema名称

public

目的端的schema名称只能有且只有一个

dbswitch.target.target-drop

是否执行先drop表然后create表命令,当target.datasource-target.drop=true时有效

true

可选值为:true、false

dbswitch.target.create-table-auto-increment

是否执启用支持create表时主键自增(只支持mysql)

true

可选值为:true、false

dbswitch.target.writer-engine-insert

是否使用insert写入数据

false

可选值为:true为insert写入、false为copy写入,只针对目的端数据库为PostgreSQL/Greenplum的有效

dbswitch.target.change-data-sync

是否启用增量变更同步,dbswitch.target.target-drop为 false 时且表有主键情况下有效

false

可选值为:true、false

注意:

  • (1)支持源端为多个数据源类型,如果dbswitch.source[i]为数组类型,i为编号,从0开始的整数;
  • (2)如果dbswitch.source[i].source-includes不为空,则按照包含表的方式来执行;
  • (3)如果dbswitch.source[i].source-includes为空,则按照dbswitch.source[i].source-excludes排除表的方式来执行。
  • (4)如果dbswitch.target.target-drop=falsedbswitch.target.change-data-synch=true;时会对有主键表启用增量变更方式同步
  • (5)对于regex-table-mapperregex-column-mappe,为基于正则表达式替换的表名映射和字段名映射,均可以为空(代表原名映射,即源的表t_a映射到目的端也为t_a)
  • (6)在配置字段映射时,可以通过将字段映射为空的方式排除制定字段

提示:如果要将源端所有表名(或者字段名)添加前缀,可以配置"from-pattern": "^","to-value": "T_";

  • (7)支持的数据库产品及其JDBC驱动连接示例如下:

MySQL/MariaDB数据库

jdbc连接地址:jdbc:mysql://127.0.0.1:3306/test?useUnicode=true&useLegacyDatetimeCode=false&serverTimezone=Asia/Shanghai&autoReconnect=true&failOverReadOnly=false&nullNamePatternMatchesAll=true&useSSL=false&rewriteBatchedStatements=true
jdbc驱动名称: com.mysql.jdbc.Driver
jdbc连接地址:jdbc:mariadb://127.0.0.1:3306/test?useUnicode=true&characterEncoding=utf-8&useSSL=false&zeroDateTimeBehavior=convertToNull&serverTimezone=Asia/Shanghai&nullCatalogMeansCurrent=true&tinyInt1isBit=false&rewriteBatchedStatements=true&useCompression=true
jdbc驱动名称: org.mariadb.jdbc.Driver

Oracle数据库

jdbc连接地址:jdbc:oracle:thin:@127.0.0.1:1521:ORCL  或   jdbc:oracle:thin:@//127.0.0.1:1521/ORCL
jdbc驱动名称:oracle.jdbc.driver.OracleDriver

SQL Server(>=2005)数据库

jdbc连接地址:jdbc:sqlserver://127.0.0.1:1433;DatabaseName=test
jdbc驱动名称:com.microsoft.sqlserver.jdbc.SQLServerDriver

PostgreSQL/Greenplum数据库

jdbc连接地址:jdbc:postgresql://127.0.0.1:5432/test
jdbc驱动名称:org.postgresql.Driver

DB2数据库

jdbc连接地址:jdbc:db2://127.0.0.1:50000/testdb:driverType=4;fullyMaterializeLobData=true;fullyMaterializeInputStreams=true;progressiveStreaming=2;progresssiveLocators=2;
jdbc驱动名称:com.ibm.db2.jcc.DB2Driver

达梦DMDB数据库

jdbc连接地址:jdbc:dm://127.0.0.1:5236
jdbc驱动名称:dm.jdbc.driver.DmDriver

人大金仓Kingbase8数据库

jdbc连接地址:jdbc:kingbase8://127.0.0.1:54321/MYTEST
jdbc驱动名称:com.kingbase8.Driver

翰高HighGo数据库(可按PostgreSQL使用)

jdbc连接地址:jdbc:postgresql://127.0.0.1:5866/highgo
jdbc驱动名称:org.postgresql.Driver

Apache Hive数据库

jdbc连接地址:jdbc:hive2://172.17.2.12:10000/default
jdbc驱动名称:org.apache.hive.jdbc.HiveDriver

注意:当前只支持hive version 3.x的账号密码认证方式。

SQLite数据库

jdbc连接地址:jdbc:sqlite:/tmp/test.db   或者  jdbc:sqlite::resource:http://172.17.2.12:8080/test.db
jdbc驱动名称:org.sqlite.JDBC

集成开发

数据迁移相关组件可以引入到其他项目中单独使用,把 middle-common 下的 middle-dbswtich 模块安装到 maven 中(在文件夹下执行 mvn clean install)

引入 maven 依赖:

<dependency>
    <artifactId>middle-dbswtich</artifactId>
    <groupId>middle-ground</groupId>
    <version>1.0</version>
</dependency>

代码开发示例:

DbswichProperties dbswichProperties = new DbswichProperties();
    //构建源表参数
    SourceDataSourceProperties dataSourceProperties = new SourceDataSourceProperties();
    List<SourceDataSourceProperties> sourceProperties = new ArrayList<>(10);
    sourceProperties.add(dataSourceProperties);
    dbswichProperties.setSource(sourceProperties);
    dataSourceProperties.setUrl("jdbc:oracle:thin:@127.0.0.1:1521:orcl");
    dataSourceProperties.setDriverClassName(DbType.ORACLE.getDriveClassName());
    dataSourceProperties.setUsername("TEST");
    dataSourceProperties.setPassword("root");
    dataSourceProperties.setFetchSize(10000);
    dataSourceProperties.setSourceSchema("TEST");
    //表名映射关系
    List<PatternMapper> tableNameMapper = new ArrayList<>(1);
    PatternMapper patternMapper = new PatternMapper();
    patternMapper.setFromPattern("test");
    patternMapper.setToValue("sync_test");
    tableNameMapper.add(patternMapper);
    dataSourceProperties.setRegexTableMapper(tableNameMapper);
    //字段映射关系
    List<PatternMapper> columnMapper = new ArrayList<>(10);
    dataSourceProperties.setRegexColumnMapper(columnMapper);
    PatternMapper columnPattern = new PatternMapper();
    columnPattern.setFromPattern("test");
    columnPattern.setToValue("test");
    columnMapper.add(columnPattern);
    PatternMapper columnPattern1 = new PatternMapper();
    columnPattern.setFromPattern("test1");
    //设置为null会不同步这个字段
    columnPattern.setToValue(null);
    columnMapper.add(columnPattern1);
    //目标表参数
    TargetDataSourceProperties targetDataSourceProperties = new TargetDataSourceProperties();
    dbswichProperties.setTarget(targetDataSourceProperties);
    targetDataSourceProperties.setUrl("jdbc:mysql://127.0.0.1:3306/test?useUnicode=true&useLegacyDatetimeCode=false&serverTimezone=Asia/Shanghai&autoReconnect=true&failOverReadOnly=false&nullNamePatternMatchesAll=true&useSSL=false&rewriteBatchedStatements=true&allowPublicKeyRetrieval=true");
    targetDataSourceProperties.setDriverClassName(DbType.MYSQL.getDriveClassName());
    targetDataSourceProperties.setUsername("root");
    targetDataSourceProperties.setPassword("root");
    targetDataSourceProperties.setTargetSchema("test");
    targetDataSourceProperties.setTargetDrop(true);
    targetDataSourceProperties.setIndexCreate(true);
    targetDataSourceProperties.setLowercase(true);
    //主键自动递增
    targetDataSourceProperties.setCreateTableAutoIncrement(true);
    targetDataSourceProperties.setChangeDataSync(false);
    MigrationService service = new MigrationService(dbswichProperties);
    //运行数据同步
    service.run();

系统运行展示

数据库异构架构图 数据库异构迁移_bc

数据库异构架构图 数据库异构迁移_数据库异构架构图_02

数据库异构架构图 数据库异构迁移_bc_03

数据库异构架构图 数据库异构迁移_bc_04

数据库异构架构图 数据库异构迁移_数据库异构架构图_05

数据库异构架构图 数据库异构迁移_数据仓库_06

数据库异构架构图 数据库异构迁移_etl_07

数据库异构架构图 数据库异构迁移_数据库异构架构图_08

结语

经测试,该 ETL 系统的同步效率跟市面上主流的 ETL 工具无异,但如果有大字段类型比如:text,clob 等,同步速度会明显降低,这一点需要注意。通过集成系统的数据同步模块,也可以将其应用到自己的系统之中,对于大数据应用,数据处理系统有着不错的使用和参考价值,代码模块划分明确,方便进行二次开发。