本文介绍在DTS任务中如何通过配置ETL,解决源实例与目标实例的数据不兼容问题和数据脱敏问题。
前提条件
已创建源和目标数据库实例,本文以RDS MySQL间同步为例,创建方法,请参见创建RDS MySQL实例。
目标实例的存储空间须大于原实例占用的存储空间。
典型应用一:非法值处理
DTS支持异构类型的数据库之间的同步和迁移,同步或迁移时会自动进行类型映射。但是仍然会出现不可避免的数据不兼容,比如MySQL同步到Oracle,源实例varchar(10) NOT NULL列的空字符串无法写入目标实例的非空列,因为Oracle会将空字符串等同于NULL。将会导致同步中断。
此类问题不能简单地跳过数据,因为会造成数据不一致。您可以为DTS任务配置ETL,使用DSL语法插入额外的转换逻辑,对非法值进行处理。
下文以RDS MySQL之间的同步为例,源实例允许NULL,目标实例不允许NULL,模拟上述问题的处理。
源实例与目标实例创建表结构如下:
源实例
CREATE DATABASE testdb; USE testdb; CREATE TABLE `src_table` ( `id` int(11) NOT NULL, `user` varchar(100) NULL, PRIMARY KEY (`id`) ) ENGINE=InnoDB DEFAULT CHARACTER SET=utf8;目标实例
CREATE DATABASE testdb; USE testdb; CREATE TABLE `dest_table` ( `id` int(11) NOT NULL, `user` varchar(100) NOT NULL, PRIMARY KEY (`id`) ) ENGINE=InnoDB DEFAULT CHARACTER SET=utf8;
创建源实例与目标实例间的同步任务。更多信息,请参见同步方案概览。
配置同步任务时,以下参数需修改。
目标已存在表的处理模式修改为忽略报错并继续执行,当目标实例存在同名表时不报错。
右键单击已选择对象中的目标表,修改表映射名称为dest_table。
在源实例插入数据,插入的user值为NULL。
INSERT INTO src_table (id) VALUES (1);因为目标实例user为非空列,因此同步任务会失败。
报错信息为:
Column 'user' cannot be null。可以为同步任务配置ETL脚本,对非法值进行处理。
在目标同步任务中单击
,选择修改ETL配置。在高级配置中,配置 ETL 功能参数选中是,DSL脚本配置为:
e_if(op_is_null(`user`), e_set(`user`, '_NULL_'))。说明DSL脚本
e_if(op_is_null(`user`), e_set(`user`, '_NULL_'))的语法组成及含义如下:op_is_null(`user`):判断user取值是否为null。e_set(`user`,'_NULL_'):设置user的值为_NULL_。e_if(op_is_null(`user`), e_set(`user`, '_NULL_')):如果user值为null,则设置为_NULL_。
DSL语法的更多介绍,请参见数据处理DSL语法简介。
配置完成后,单击下一步预检查并启动。
查看同步任务是否恢复。
在目标实例查询表数据,查看NULL是否被替换为_NULL_。
典型应用二:数据脱敏
DTS可用于数据备份、数据集成等场景,在这些场景中,可能需要对数据进行统计分析,为保证用户的隐私数据的安全,您可以为DTS任务配置ETL,使用DSL语法插入额外的转换逻辑,对敏感数据进行脱敏。
配置ETL使用的DSL脚本包含了常见的数据转换函数(哈希值计算等),可用于数据脱敏。本文以身份证号和姓名脱敏为例。
源实例创建数据库表并插入测试数据。
CREATE DATABASE testdb2; USE testdb2; CREATE TABLE user(id int NOT NULL PRIMARY KEY, id_card varchar(100) NOT NULL, name varchar(100) NOT NULL); INSERT INTO user VALUES(1, '123456789', '张三'); INSERT INTO user VALUES(2, '987654321', '李四');创建源实例与目标实例间的同步任务。将
testdb2中的表user同步到目标实例。更多信息,请参见同步方案概览。在配置任务对象及高级配置步骤的高级配置中,配置 ETL 功能选择是,在输入框中填写如下数据脱敏语句。
e_compose( e_if(op_eq(__TB__,'user'),e_set(`id_card`, str_md5(`id_card`))), e_if(op_eq(__TB__,'user'),e_set(`name`, str_mask(`name`, 1, 2, '*'))) )说明DSL脚本的语法组成及含义如下:
str_md5(`id_card`):对id_card的值进行MD5加密。str_mask(`name`, 1, 2, '*'):将name的第1位和第2位取值替换为星号(*)。e_set(`id_card`, str_md5(`id_card`)):设置id_card的值为MD5加密后的密文。e_set(`name`, str_mask(`name`, 1, 2, '*')):设置name的值为脱敏后的数据。e_if(op_eq(__TB__,'user'),e_set(`id_card`, str_md5(`id_card`))),:将user表中id_card的值设置为MD5加密后的密文。e_if(op_eq(__TB__,'user'),e_set(`name`, str_mask(`name`, 1, 2, '*'))):将user表中name的值设置为脱敏后的数据。e_compose( e_if(op_eq(__TB__,'user'),e_set(`id_card`, str_md5(`id_card`))), e_if(op_eq(__TB__,'user'),e_set(`name`, str_mask(`name`, 1, 2, '*')))):对user表中id_card的值进行MD5加密,并对name的值用星号(*)替换进行脱敏。
DSL语法的更多介绍,请参见数据处理DSL语法简介。
在目标实例查看同步的数据是否脱敏,查看name的值是否被用星号(*)脱敏。