注册
CVT 数据清洗转换实战
专栏/技术分享/ 文章详情 /

CVT 数据清洗转换实战

Cath Palug 2026/09/04 81 0 0
摘要

DMDRS CVT 数据清洗转换实战:搭建与DML操作验证

CVT(数据清洗转换)是 DMDRS 的重要功能模块,支持在数据同步过程中对
INSERT、UPDATE、DELETE 操作进行实时改写。本文带你完成 CVT
环境搭建,并编写.cvt脚本验证三种 DML 操作的转换效果。

1. CVT 是什么?

CVT(Cleansing & Transformation)是 DMDRS 的数据清洗转换模块,在 EXEC
端以行记录为单位,对同步过来的每一条 DML 操作进行转换处理。

核心能力

  • 为 INSERT 操作添加标识列和时间戳

  • 将 UPDATE 拆分为两条 INSERT(修改前 + 修改后)

  • 将 DELETE 转为 INSERT(保留删除前的数据)

适用场景:过程数据同步、操作审计、历史追溯。

2. 环境准备

2.1 前提条件

  • DMDRS 主备环境已搭建完成(参考《DMDRS 主备搭建完全指南》)

  • EXEC 模块正常运行,能接收 CPT 投递的数据

2.2 CVT 脚本目录

在 EXEC 工作目录下创建cvt_scripts文件夹:

cd /data/dmdrs5/bin_exec_dm8_5345

mkdir cvt_scripts

3. 配置 EXEC 启用 CVT

编辑exec.xml,添加cvt_dir配置项:

<exec>

<!-- 其他配置保持不变 -->

<cvt_dir>cvt_scripts</cvt_dir>

</exec>

完整示例

<exec>

<name>exec_dm8</name>

<login>

<dbtype>dm8</dbtype>

<server>192.168.21.135</server>

<user>TEST_DB</user>

<pwd>Dameng123</pwd>

<port>5237</port>

</login>

<cvt_dir>cvt_scripts</cvt_dir>

</exec>

4. 编写 CVT 脚本

4.1 脚本文件结构

cvt_scripts/

├── global.glb # 全局变量定义

└── full_cvt.cvt # DML 转换规则

4.2 全局定义(global.glb)

GLOBAL

DECLARE

g_total_rows INT;

BEGIN

g_total_rows := 0;

DRS_SYS.PUT_LINE(’>>> CVT 初始化完成’);

END;

CLEAN

BEGIN

DRS_SYS.PUT_LINE(’>>> CVT 清理完成,总处理记录数: ’ ||
g_total_rows);

END;

4.3 DML 转换脚本(full_cvt.cvt)

TABLE DMDRS.EMPL1

DECLARE

old_cols DRS.DML_COL_ARR;

new_cols DRS.DML_COL_ARR;

i INT;

v_op VARCHAR(16);

BEGIN

v_op := UPPER(op.#OP);

g_total_rows := g_total_rows + 1;

DRS_SYS.PUT_LINE(’>>> 第 ’ || g_total_rows || ’ 条, 操作: ’
|| v_op);

– INSERT: 添加标识 I 和时间戳

IF v_op = ‘INSERT’ THEN

op.ADD_COL(‘BIAOSHI’, ‘I’);

op.ADD_COL(‘OP_TIME’, SYSDATE());

op.exec();

RETURN;

– UPDATE: 拆分为两条 INSERT(D + I)

ELSIF v_op = ‘UPDATE’ THEN

old_cols := op.GET_OLDCOLS();

new_cols := op.GET_NEWCOLS();

– 旧数据 -> INSERT, 标记 D

op.#OP := ‘INSERT’;

op.SET_COLS(old_cols);

op.ADD_COL(‘BIAOSHI’, ‘D’);

op.ADD_COL(‘OP_TIME’, SYSDATE());

op.exec();

– 新数据 -> INSERT, 标记 I, 补全未修改列

op.#OP := ‘INSERT’;

op.SET_COLS(new_cols);

FOR i IN 1…old_cols.SIZE LOOP

IF op.HAS_NEWCOL(old_cols[i].NAME) = 0 THEN

op.ADD_COL(old_cols[i].NAME, old_cols[i].VALUE);

END IF;

END LOOP;

op.ADD_COL(‘BIAOSHI’, ‘I’);

op.ADD_COL(‘OP_TIME’, SYSDATE());

op.exec();

RETURN;

– DELETE: 转为 INSERT, 标记 D

ELSIF v_op = ‘DELETE’ THEN

old_cols := op.GET_OLDCOLS();

op.#OP := ‘INSERT’;

op.SET_COLS(old_cols);

op.ADD_COL(‘BIAOSHI’, ‘D’);

op.ADD_COL(‘OP_TIME’, SYSDATE());

op.exec();

RETURN;

ELSE

DRS_SYS.PUT_LINE(’>>> 未知操作: ’ || v_op);

RETURN;

END IF;

END;

5. 目标表设计

由于 UPDATE 会拆成两条
INSERT,目标表必须支持同一业务主键的多版本共存。推荐使用自增列作为主键:

– 目标表(在目标端执行)

CREATE TABLE TEST_DB.EMPL1_TARGET (

SEQ_ID BIGINT AUTO_INCREMENT PRIMARY KEY,

ID INT,

NAME VARCHAR(50),

AGE INT,

SALARY DEC(10,2),

BIAOSHI VARCHAR(10),

OP_TIME TIMESTAMP

);

脚本中的op.exec()默认使用源表名EMPL1,如果要写入目标表EMPL1_TARGET,修改为op.exec(EMPL1_TARGET)即可。

6. 启动与验证

6.1 启动 EXEC

cd /data/dmdrs5/bin_exec_dm8_5345

pkill -9 -f “drsvr.*exec”

rm -rf CACHE_* LLOG_* # 清缓存,重新加载脚本

nohup ./drsvr exec.xml >> exec.log 2>&1 &

查看脚本加载状态:

grep “cvt load success” exec.log

6.2 验证 DML 转换

源端执行以下操作:

– 1. INSERT

INSERT INTO DMDRS.EMPL1 VALUES (1, ‘张三’, 25, 5000.00);

COMMIT;

– 2. UPDATE

UPDATE DMDRS.EMPL1 SET AGE = 26, SALARY = 5500.00 WHERE ID = 1;

COMMIT;

– 3. DELETE

DELETE FROM DMDRS.EMPL1 WHERE ID = 1;

COMMIT;

目标端查询结果:

SELECT SEQ_ID, ID, NAME, AGE, SALARY, BIAOSHI, OP_TIME

FROM TEST_DB.EMPL1_TARGET ORDER BY SEQ_ID;

预期结果


SEQ_ID ID NAME AGE SALARY BIAOSHI OP_TIME

1 1 张三 25 5000.00 I 2026-08-24
10:00:01

2 1 张三 25 5000.00 D 2026-08-24
10:00:05

3 1 张三 26 5500.00 I 2026-08-24
10:00:05

4 1 张三 26 5500.00 D 2026-08-24
10:00:10


共 4 条记录:INSERT (I) → UPDATE 旧数据 (D) → UPDATE 新数据 (I) → DELETE
(D),完整记录了该数据的所有变更历史。

7. 调试技巧

7.1 日志掩码配置

DRS_SYS.PUT_LINE需要PRINT_TRACE掩码才能输出。在exec.xml中添加:

<log_mask>PRINT_TRACE</log_mask>

7.2 查看调试日志

tail -f exec.log | grep “>>>”

8. 常见问题

8.1 脚本修改后不生效

原因:EXEC 缓存了旧脚本。

解决:停止 EXEC,删除CACHE_*和LLOG_*目录后重启。

8.2 UPDATE 拆分后只有一条 INSERT

原因:目标表主键为业务主键,第二条 INSERT 被主键冲突拒绝。

解决:改用自增列作为主键(参考第5节)。

8.3 PUT_LINE 无输出

原因:log_mask未包含PRINT_TRACE。

解决:在exec.xml中配置<log_mask>PRINT_TRACE</log_mask>。

结语

本文完成了 CVT 环境的搭建,并通过一个完整的.cvt脚本验证了
INSERT、UPDATE、DELETE 三种 DML 操作的转换效果。核心要点:

  1. 目标表使用自增主键,承载多版本数据

  2. UPDATE 拆分时注意补全未修改的列

  3. 调试时记得配置PRINT_TRACE掩码

有了这个基础,你可以进一步扩展 CVT 脚本,实现更复杂的数据转换逻辑。

评论
后发表回复

作者

文章

阅读量

获赞

扫一扫
联系客服