本文介紹在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的值是否被用星號(*)脫敏。脫敏