Kettle (6) - 跨数据库数据迁移几个细节

本篇基于假设的场景:将 SQL Server 数据库的表迁移到 MySQL 数据库。之前写过一篇从 SQLite 到 MySQL 的,但当时目标数据库的表创建是手写 SQL 语句来创建的。最近在做数据处理操作的时候,需要用不同的数据源来作性能和其他方面的比较,所以做了不少数据的腾挪。数据在不同数据库间迁移的时候,希望用尽量自动化的方式创建数据表。比较过几个工具,最后还是觉得 kettle 是最合适。将 kettle 数据迁移的几个细节记录一下。

数据库 jar 包

我使用的是 kettle 7.1 版,本来是已经下载了 8.2,但感觉 kettle版本越高,启动速度越慢,又重新退回到 7.1。好久没用过 kettle,这次重新捡起来,发现 kettle 竟然连常见的数据库驱动,比如 mysql connector,都没有提供。需要自己下载。

MySQL 和 Sql Server 操的 jar 包都可以在 Maven Repository 中下载:MySql jar 包地址:https://mvnrepository.com/artifact/mysql/mysql-connector-java

Sql Server 数据库操作的 jar 包(JTDS)地址:https://mvnrepository.com/artifact/net.sourceforge.jtds/jtds

下载 jar 包后,放在 kettle 安装包里面的 lib 文件夹中,需要重启 kettle。

如果通过 kettle 迁移数据库,强烈建议不要用 MS Access 数据库。因为 JDBC 没有直接操作 MS Access 的 jar 包,1.7之前只能通过 JDBC-ODBC bridge,但 Java 8 之后,这个Bridge 被 Oracle 公司移除了。

配置与 SQL Server 和 MySQL 的连接

启动 spoon,新建一个转换 (Transformation),在「主对象树」中,选择 「DB连接」节点,右键,新建一个数据库连接向导,连接名称为 sqlserver:

在这里插入图片描述
点击 Next 按钮,输入服务器名称,TCP/IP 端口和数据库名称:

在这里插入图片描述
点击 Next 进入下一界面,输入用户名和密码。然后点击 测试数据库连接 测试是否能连接成功。

在这里插入图片描述
因为我使用的是 SQL Server 2017 Express 版,所以默认的端口不是 1433。如何查看这个端口呢?打开 SQL Server 配置管理器,如果 TCP/IP 没有启用,需要启用 TCP/IP 连接方式。

在这里插入图片描述
然后选中 TCP/IP,右键,查看属性,在最后有一个 IPALL,这里就是 Express 版的端口。

在这里插入图片描述

用同样的方式建立与 MySQL 数据库的连接。

在这里插入图片描述

多表复制向导

通过菜单【工具】> 【向导】> 【复制多表向导】,打开下面的界面。左边选择 sqlserver,右边选择 mysql。

在这里插入图片描述
点击 「Next」,选择需要迁移的表:

在这里插入图片描述
输入 job Name 和 Directory,然后点击 Finish

在这里插入图片描述

Kettle 生成下面的 job,非常直观:

在这里插入图片描述
到这里,基本上,执行运行操作就可以自动创建表,将数据从源数据库复制到目标数据库。但要注意两个问题:

  1. 目标数据库没有包含源数据表的 primary key 和 foreign key 等信息,需要手工补充
  2. 注意源数据库和目标数据库的 encoding 是否一致,避免中文乱码

解决第一个问题。双击作业的步骤「创建表[stock_movement_headers]」,显示界面如下:

在这里插入图片描述

本步骤执行 SQL 语句来创建表,但没有同时创建 primary key,可以对 SQL 语句进行更改:

在这里插入图片描述
对 stock_movement_details 表也用同样的方法设置数据表的 primary key。

第二个问题,为了避免乱码,对源数据库和目标数据库的 encoding。方法是双击 DB连接,切换到选项页面,增加一个命名参数 characterEncoding。

在这里插入图片描述

在表输出步骤创建表

一般情况下,Transformation 的表输入表输出用于传输数据表的数据,但也可以在创建步骤的时候执行创建表的 SQL 语句,方法如下。以我刚刚创建的 Transformation 为例,增加一个表输入

在这里插入图片描述

增加一个表输出步骤,与表输入连接。对表输出步骤设置如下:
在这里插入图片描述

其实此时 stock_movement_headers 表并不存在,但可以点击 「SQL」按钮,帮助生成相应的 SQL 语句。当我们点击的时候,弹出界面如下:

在这里插入图片描述
对 SQL 语句稍作修改,然后点击执行,即可生成 stock_movement_headers 表。然后再执行 transformation,实现数据的传输。

/** * 源数据库库连接池配置 * */ ConnPoolConfig config = new ConnPoolConfig(); config.setMaxPoolSize(30); config.setInitialPoolSize(20); config.setUrl("jdbc:sqlserver://192.168.0.222;databaseName=ciems"); config.setDriverClass("com.microsoft.sqlserver.jdbc.SQLServerDriver"); config.setUsername("sa"); config.setPassword("Password2017"); /** * 源库 * "queryDB" DBManager的自定义名称 * config 连接池配置 */ DBManager queryDb = new DBManager("queryDB",config); /** * 目标数据库连接池配置 * */ ConnPoolConfig tarconfig = new ConnPoolConfig(); tarconfig.setMaxPoolSize(30); tarconfig.setInitialPoolSize(20); tarconfig.setDriverClass("com.mysql.jdbc.Driver"); tarconfig.setUrl("jdbc:mysql://localhost:3306/datatransfer?useUnicode=true&characterEncoding=UTF8&useSSL=true"); tarconfig.setPassword("accp"); tarconfig.setUsername("root"); /** * 目标库 */ DBManager insertDb = new DBManager("insertDB",config); /** *做数据导入处理时的接口 * */ InsertHandler handler = new DBInsertHandlerImpl("t_big_data",null,insertDb); /** * 迁移任务的配置,配置关键信息项 */ ApplicationConfig apConfig = new ApplicationConfig("t_big_data"); apConfig.setQueryThreadNum(8); //指定查询线程数量,不指定默认为8 apConfig.setDataNum(5000); //设置每次从源库中抽取的数量 不指定默认为5000 /** * 源表的匹配条件 * 如果希望源表中符合条件的才迁移,请配置此项,禁止加where,请按照以下格式 */ apConfig.setConditionSql("0=0"); /** * 入库方式 * ** * 增量入库 ZLRK, (暂未实现) * 追加入库 ZJRK, (目标库有源表结构的基础上,增加源表的所有数据到目标库中) * 刷新入库 SXRK, (删除目标库的源表结构,自动创建并导入数据) * 更新入库 GXRK (暂未实现) * ** */ apConfig.setInsertType(InsertType.SXRK); /** * 日志线程,开启时可更直观的从标准输出流里观察到运行状态,不指定默认关闭 */ apConfig.setOpenLogThread(true); /** * 生命周期接口,线程不完全 * 分别有以下几个生命周期方法 * createTableDone() 目标库被创建表结构时调用一次 * queryDone(boolean result, int start, int end, long time,Throwable e) * 有数据从源表中查询到数据时被调用,直到任务完成 * result 查询结果 * start 查询起始行 * end 查询结束行 * time 共耗时 单位:ms * e 查询失败时抛出的异常 * insertDone(boolean result, int num, int errorNum, long time,Throwable e) * 有数据导入到目的库时被调用,直到任务完成 * result 导入结果 * num 导入总数量 * errorNum异常数量 * e 导入失败时抛出的异常 * taskDone(int all, int doneNum, int errorNum, long time,List errorRows, List e) * 任务完成时被调用 * all 任务总数据量 * doneNum 已完成的数据量 * errorNum异常的数据量 * time 总耗时 * errorRows异常的行记录 * e 所有的异常 */ TaskRunLog runLog = new TaskRunLogImpl(); /*** * 任务迁移核心类 * 以下是构造方式之一 * ApplicationConfig apConfig:任务关键配置 * DBManager queryDb: 源库 * InsertHandler handler:导入处理器 */ DataThransferApplication app = new DataThransferApplication(apConfig,queryDb,handler,runLog); /** * 初始化任务 */ app.init(); /** * 任务开始 */ app.start();
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值