本文介绍在DTS任务中如何通过配置ETL,解决源实例与目标实例的数据不兼容问题和数据脱敏问题。

前提条件

  • 已创建源和目标数据库实例,本文以RDS MySQL间同步为例,创建方法,请参见 创建RDS MySQL实例
  • 目标实例的存储空间须大于原实例占用的存储空间。

典型应用一:非法值处理

DTS支持异构类型的数据库之间的同步和迁移,同步或迁移时会自动进行类型映射。但是仍然会出现不可避免的数据不兼容,比如MySQL同步到Oracle,源实例 varchar(10) NOT NULL 列的空字符串无法写入目标实例的非空列,因为Oracle会将空字符串等同于NULL。将会导致同步中断。

此类问题不能简单地跳过数据,因为会造成数据不一致。您可以为DTS任务配置ETL,使用 DSL语法 插入额外的转换逻辑,对非法值进行处理。

说明 下文以RDS MySQL之间的同步为例,源实例允许NULL,目标实例不允许NULL,模拟上述问题的处理。
  1. 源实例与目标实例创建表结构如下:
    • 源实例
      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;
  2. 创建源实例与目标实例间的同步任务。更多信息,请参见 同步方案概览 同步任务
    配置同步任务时,以下参数需修改。
    • 目标已存在表的处理模式 修改为 忽略报错并继续执行 ,当目标实例存在同名表时不报错。
    • 右键单击 已选择对象 中的目标表,修改表映射名称为 dest_table
    同步任务参数修改
  3. 在源实例插入数据,插入的 user 值为 NULL
    INSERT INTO src_table (id) VALUES (1);
    因为目标实例 user 为非空列,因此同步任务会失败。 同步任务失败
    报错信息为: Column 'user' cannot be null 报错信息
  4. 可以为同步任务配置ETL脚本,对非法值进行处理。
    1. 在目标同步任务中单击 点点点 ,选择 修改ETL配置 修改ETL
    2. 在高级配置中, 配置ETL功能 参数选中 ,DSL脚本配置为: e_if(op_is_null(`user`), e_set(`user`, '_NULL_')) 配置ETL功能
      说明 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语法简介

    3. 配置完成后,单击 下一步预检查并启动
  5. 查看同步任务是否恢复。 修改ETL后DTS状态
  6. 在目标实例查询表数据,查看 NULL 是否被替换为 _NULL_ null

典型应用二:数据脱敏

DTS可用于数据备份、数据集成等场景,在这些场景中,可能需要对数据进行统计分析,为保证用户的隐私数据的安全,您可以为DTS任务配置ETL,使用 DSL语法 插入额外的转换逻辑,对敏感数据进行脱敏。

配置ETL使用的DSL脚本包含了常见的数据转换函数(哈希值计算等),可用于数据脱敏。本文以身份证号和姓名脱敏为例。

  1. 源实例创建数据库表并插入测试数据。
    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', '李四');
  2. 创建源实例与目标实例间的同步任务。将 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语法简介

  3. 在目标实例查看同步的数据是否脱敏,查看 name 的值是否被用星号(*)脱敏。 脱敏