本文介紹在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腳本,對非法值進行處理。
- 查看同步任務是否恢復。
- 在目標實例查詢表數據,查看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的值是否被用星號(*)脫敏。