注册
DMDRS 增量链路操作
专栏/技术分享/ 文章详情 /

DMDRS 增量链路操作

JcRapunzel 2026/09/18 286 0 0
摘要

场景:目标端数据已由备份还原与源端一致(未做 add dict),需补齐增量同步链路

〇、起点 LSN 决策(先决策,再动手)

实际情况 采用做法 命令
备份刚还原完,源库此后无任何变更 以当前最新 LSN 为起点(最简单,推荐) alter cpt_dm8 add dict "<FILTER>" LSN
源库自备份后有变更,需补齐这段时间 起点=备份时刻 LSN,重放这段日志 alter cpt_dm8 set lsn from "<备份目录>" 或 alter cpt_dm8 set lsn <LSN值>
备份 LSN 拿不到 / 归档区间不完整 / 无法接受重放 放弃增量补数,改全量重装或重做备份还原 alter cpt_dm8 add table "<FILTER>" DROP\|CREATE\|INSERT\|INDEX\|TABLE\|CHECK\|GROUP

[!IMPORTANT] 起点必须与"目标库数据所代表的时点"严格对应

  • 取早了 → 重复数据 / 报错
  • 取晚了 → 永久漏数据(检查点推进后无法追回)
  • DSC 源必须给各节点 LSN,不能指定单一 LSN:alter cpt_dsc set lsn "0#123456,1#123457"

Step 0 前置检查

0.1 源库:归档与逻辑日志(★必需,三列都不能为 0)

SELECT PARA_NAME, PARA_VALUE, SESS_VALUE, FILE_VALUE FROM V$DM_INI WHERE PARA_NAME IN ('ARCH_INI','RLOG_APPEND_LOGIC');
  • [达标] ARCH_INI=1 且 RLOG_APPEND_LOGIC 为非 0(1 常规 / 2 全列日志〔Doris 目标必须 2〕/ 3)
  • [失败处置] 未开启:alter database mount; → alter database archivelog; → alter database add archivelog 'DEST=/dm8/data/arch,TYPE=LOCAL,FILE_SIZE=512,SPACE_LIMIT=10240'; → alter database open;,再 call sp_set_para_value(1,'RLOG_APPEND_LOGIC',1);

0.2 源库:归档文件是否连续可用

SELECT * FROM V$ARCHIVED_LOG ORDER BY 1 DESC LIMIT 20;
  • [达标] 从"备份时点 LSN"至今的归档文件齐全(否则无法重放)

0.3 源端控制台体检

cd <SRC_DMDRS_HOME>/bin
./drcsl cpt_utf8.xml
connect
show mode
show cpt_dm8 database connect
show cpt_dm8 conf
show cpt_dm8 log arch 20
show cpt_dm8 log error
  • [达标] CPT 模块存在且可管理;源库连接正常;login/dict_dir/send 配置符合预期;归档列表可见
  • [失败处置] database connect 为空 → 查 login 的 dbtype/server/port/user/pwd;连接被拒 → 查源库监听与账号

0.4 目标端控制台体检

cd <DST_DMDRS_HOME>/bin
./drcsl exec_utf8.xml
connect
show mode
show exec_dm8 database connect
show exec_dm8 stor
show exec_dm8 log error
  • [达标] EXEC 模块运行中;目标库连接正常;磁盘 ≥10GB(<10GB 不执行检查点,会反压阻塞源端检查点)
  • [失败处置] 磁盘不足 → 清理 &lt;DST_DMDRS_HOME> 下 log/检查点目录后再继续

0.5 两端一致性核对(★数据一致也要核,否则映射错位)

-- 两端分别执行,逐项比对 SELECT PARA_NAME, PARA_VALUE FROM V$DM_INI WHERE PARA_NAME IN ('CASE_SENSITIVE','LENGTH_IN_CHAR','CHARSET','PAGE_SIZE','EXTENT_SIZE');
  • [达标] CASE_SENSITIVE、字符集一致
  • [失败处置] 不一致 → 表名/模式名映射会错位,需评估是否重建目标库;字符集差异可用 char_code 补偿

0.6 数据一致性留证(重放前的"基准快照")

-- 源库与目标库分别执行同一段,结果应一致,脚本留档 SELECT 'RESOURCES.表1' AS TAB, COUNT(*) AS CNT FROM "RESOURCES"."表1" UNION ALL SELECT 'RESOURCES.表2', COUNT(*) FROM "RESOURCES"."表2";
  • [达标] 两端行数一致(后续用它判断重放是否补齐)

Step 1 目标库清理"备份带来的 DRS 残留"(★最容易漏)

备份取自源库,若源库当时已装 DDL 同步辅助对象,这些对象会随备份一起还原到目标库,必须清理。

1.1 目标库排查 DRS 辅助对象与触发器

SELECT NAME, TYPE$, SUBTYPE$ FROM SYSOBJECTS WHERE NAME LIKE 'DRS\_%' ESCAPE '\'; SELECT NAME, SUBTYPE$ FROM SYSOBJECTS WHERE SUBTYPE$ = 'TRIG' AND NAME LIKE 'DRS\_%' ESCAPE '\';

1.2 按排查结果清理

-- 辅助表(示例,按实际对象名逐个处理;DRS_$DDL_* 系列为 DDL 同步辅助表) DROP TABLE "模式名"."DRS_$DDL_COL" ; -- 库级触发器 DROP TRIGGER "模式名"."DRS_$DDL_TRIG" ;

注意顺序:先删触发器,再删辅助表。删之前先确认这些对象确实来自源库备份、且目标端自己要重新初始化(后续 Step 4.5 会在源库侧建立,不依赖目标端残留)。

1.3 目标端清空陈旧字典

show exec_dm8 dict
alter exec_dm8 clear dict          # 不指定表名=清所有表字典;初始阶段可安全执行
show exec_dm8 dict                 # 应变为空
  • [达标] 目标端无 DRS_ 残留对象;字典已清空
  • [失败处置] 对象删除报依赖错误 → 按提示先删依赖对象/触发器

Step 2 源端停止 CPT

stop cpt_dm8
show mode
  • [达标] CPT 状态为"已停止"
  • [!] set lsn 与 add dict 都要求 CPT 停止且无装载活动
  • [失败处置] 若有装载活动:show cpt_dm8 load status 查看,必要时 stop load / stop table(注意:停止装载不删除已装载数据)

Step 3 设定增量起点 LSN(按第〇节决策)

# 情况 2:需要补备份后的变更 —— 方式一,直接从备份集/备份文件读取(仅 DM7/DM8 单机、DSC)
alter cpt_dm8 set lsn from "/dm8/backup/full_bak_YYYYMMDD"

# 方式二:显式指定 LSN 值
alter cpt_dm8 set lsn <LSN值>

# DSC 多节点(各节点 LSN,不能给单一值)
alter cpt_dsc set lsn "0#<LSN0>,1#<LSN1>"
# 全库(所有模式的所有表)
alter cpt_dm8 add dict "sch.name is not null" LSN

# 按模式
alter cpt_dm8 add dict "sch.name='RESOURCES'" LSN

[!CAUTION] 副作用
set lsn 会向目标端发送清理命令,释放目标端所有未接收提交操作的活动事务 → 会导致同步数据丢失。仅在初始化/重建阶段执行。

情况 1(备份后源库无变更)可跳过本步,直接用 Step 4 的 LSN 掩码。

  • [达标] 命令无报错返回;show cpt_dm8 conf 中相关配置符合预期

Step 4 添加离线字典(增量同步核心,不做装载)

4.1 添加字典

# 全库(所有模式所有表)
alter cpt_dm8 add dict "sch.name is not null"

# 按模式
alter cpt_dm8 add dict "sch.name='RESOURCES'"

# 按表 / 按模糊
alter cpt_dm8 add dict "sch.name='RESOURCES' and tab.name='EMPLOYEE'"
alter cpt_dm8 add dict "sch.name='RESOURCES' and tab.name like 'E%'"

# ★情况 1(备份后源库无变更):加 LSN 掩码,从当前时刻起同步
alter cpt_dm8 add dict "sch.name is not null" LSN
alter cpt_dm8 add dict "sch.name is not null" LSN|<LSN值>     # 显式值不能为 0

要点:

  • add dict 只做增量、不自动全量装载(正是本场景所需);add table 才会装载 → 会重复数据
  • LSN 掩码:小于该 LSN 的日志不分析投递;不指定值 = 当前最新 LSN;不用掩码时字典 LSN=0(从头解析)
  • 场景矩阵:源表存在 + 源端字典文件存在 → 只支持 update;字典不存在(本场景)→ add/update 都可
  • 嵌套表要分别添加父表和嵌套子表
  • like 通配符必须转义:tab.name like 'T\_%' escape '\';双引号内区分大小写

4.2 字典校验

show cpt_dm8 dict all
show cpt_dm8 dict check all
show cpt_dm8 table version "RESOURCES.EMPLOYEE"
show cpt_dm8 table attr "RESOURCES.EMPLOYEE"
  • [达标] dict all 中目标表齐全;dict check all 的"是否正确"列全为 YES;表的 LSN 与预期起点一致
  • [失败处置] NO → 看"错误信息"列;源表结构已变则 alter cpt_dm8 update dict "&lt;FILTER>" 刷新

4.5(可选)DDL 同步初始化

-- 源库:系统表方式需要的参数 call sp_set_para_value(1,'RLOG_APPEND_SYSTAB_LOGIC',1);
-- 源端安装目录 bin/scripts 下的 DM8 DDL 同步脚本已在源库执行(脚本名以实际安装目录为准)
-- 同步哪些 DDL(动态可改,写回 XML;分隔符 : 或 | 不能混用)
set cpt_dm8 ddl_mask table|index|check|view|sequence|procedure|function|trigger|package|type|synonym
show cpt_dm8 conf ddl_mask

不用掩码时默认只同步"表/索引/约束"的 DDL;配空 = 所有 DDL 都不同步。
需做表空间映射时开 ddl_with_ts=1;用系统表方式同步创建表空间后须执行 ALTER CPT ADD DICT "SCH.NAME IS NOT NULL" 更新字典。


Step 5 启动 CPT 并验证增量开始流动

start cpt_dm8
show mode
show cpt_dm8 parse
show cpt_dm8 send
show cpt_dm8 table all
show cpt_dm8 ckpt
show cpt_dm8 log error

源端判读

指标 达标
解析状态 / 当前解析 LSN 非 0 且递增(恒为 0 = 没有可解析的字典)
发送状态 / 当前发送 LSN、发送流量、发送次数 递增
table all 出现插入/更新/删除操作计数
ckpt 检查点 LSN 推进、状态不长时间卡在某一阶段

目标端判读

show exec_dm8 state
show exec_dm8 info
show exec_dm8 dict
show exec_dm8 group
show exec_dm8 ckpt
show exec_dm8 link lag
show exec_dm8 lag
show exec_dm8 error table
指标 达标
接收状态 空闲(正常待命)
最新接收日志 LSN / 接收日志时间 两者都推进
接收字节数 / 接收日志数 / 影响行数 增长
link lag 整体延迟 < 1 秒 = 链路无同步延迟(手册判定标准)
group 最新提交 LSN 推进
error table 为空

观感陷阱:①源库与源 DMDRS 所在 OS 时间不一致时,延迟显示不准;②目标端磁盘 <10GB 不执行检查点 → 反压源端,看似链路卡死。


Step 6 端到端确证(★用独立测试表,别动业务表)

6.1 源库造数据

CREATE TABLE "RESOURCES"."DRS_LINK_TEST"(ID INT PRIMARY KEY, C1 VARCHAR(50)); INSERT INTO "RESOURCES"."DRS_LINK_TEST" VALUES (1,'t1'); COMMIT; INSERT INTO "RESOURCES"."DRS_LINK_TEST" VALUES (2,'t2'); COMMIT; UPDATE "RESOURCES"."DRS_LINK_TEST" SET C1='t1_upd' WHERE ID=1; COMMIT; DELETE FROM "RESOURCES"."DRS_LINK_TEST" WHERE ID=2; COMMIT;

6.2 源端加入同步(测试表两端均无数据,可用 add table 自动建表+装载)

alter cpt_dm8 add table "sch.name='RESOURCES' and tab.name='DRS_LINK_TEST'"
show cpt_dm8 load status
show cpt_dm8 load table "RESOURCES.DRS_LINK_TEST"
  • [达标] 装载状态走到 COMPLETE

6.3 目标库验收

SELECT * FROM "RESOURCES"."DRS_LINK_TEST";
  • [达标] 只剩 1 行,ID=1、C1='t1_upd' → INSERT/UPDATE/DELETE 三种增量全部生效 = 链路有效

6.4 控制台留证

show cpt_dm8 table "RESOURCES.DRS_LINK_TEST"
show cpt_dm8 send
show exec_dm8 lag objname RESOURCES.DRS_LINK_TEST
show exec_dm8 error table

6.5 业务表补数校验(与 Step 0.6 基准比对)

-- 两端分别执行,行数应一致;若源库备份后有变更,重放完成后应相等 SELECT 'RESOURCES.表1' AS TAB, COUNT(*) AS CNT FROM "RESOURCES"."表1" UNION ALL SELECT 'RESOURCES.表2', COUNT(*) FROM "RESOURCES"."表2";

6.6 清理测试表

alter cpt_dm8 terminate dict "RESOURCES.DRS_LINK_TEST"
DROP TABLE "RESOURCES"."DRS_LINK_TEST"; -- 两端分别执行

Step 7 参数完善(从"能跑"到"稳")

show cpt_dm8 conf
show exec_dm8 conf
参数 位置 建议 说明
error_policy 目标 exec.xml 必配 默认 0=终止同步(任何入库报错都停链路);1=忽略错误继续(丢弃出错操作);2=MERGE INTO 兜底(仅有主键表且需全列日志,与 exec_nowait 冲突)。不可动态改,改后重启目标服务
char_code CPT / EXEC 两端字符集不同才配 相同则用默认(转换影响性能)
group(max_thr/merge_policy/max_merge_row) 目标 exec.xml 按并发与负载调 desc/exec_policy 启动后不能改(需清环境);merge_policy 默认 2,PostgreSQL/Kingbase 目标必须 0
map CPT send / EXEC group 收敛 把 *.*==*.* 收窄为按模式逐条,避免把系统对象纳入判断
enable_lob CPT 默认 1 有大对象列时保持开启
ROWID 辅助 / calc_md5_col_num CPT / EXEC 无主键表才需要 无主键表的 UPDATE/DELETE 定位依赖 ROWID 辅助列或行 MD5
mem_size base 建议 8~16(GB) 默认 16;过小在大装载/多表增量时内存不足
mgr_port base 非默认值更稳 手册建议不用默认 5345;改动须同步改对端 send/port

附:达标总表(验收签字用)

# 检查项 命令 达标标准 结果
1 源库归档+逻辑日志 V$DM_INI ARCH_INI=1、RLOG_APPEND_LOGIC≠0 ☐
2 归档区间完整 show cpt_dm8 log arch 备份时点至今齐全 ☐
3 两端一致性参数 V$DM_INI CASE_SENSITIVE/字符集一致 ☐
4 目标端无 DRS 残留 SYSOBJECTS LIKE 'DRS\_%' 无残留辅助对象/触发器 ☐
5 目标端字典已清 show exec_dm8 dict 清空 ☐
6 起点 LSN 与数据时点匹配 set lsn / LSN 掩码 与备份时点对应 ☐
7 源端字典齐全且正确 show cpt_dm8 dict check all 全 YES ☐
8 解析 LSN 推进 show cpt_dm8 parse 非 0 且递增 ☐
9 发送 LSN 推进 show cpt_dm8 send 递增 ☐
10 目标端接收推进 show exec_dm8 state/info LSN 与时间均推进 ☐
11 链路整体延迟 show exec_dm8 link lag < 1 秒 ☐
12 无同步错误 show exec_dm8 error table 空 ☐
13 端到端三类 DML Step 6 全量+INSERT/UPDATE/DELETE 均落地 ☐
14 业务表行数一致 Step 0.6 对比 两端一致 ☐
15 error_policy 已配 show exec_dm8 conf error_policy 非默认 0(按需 1 或 2) ☐

附:常见故障速查

现象 最可能原因 处置
解析 LSN / 发送 LSN 恒为 0 未添加字典/字典不成功 Step 4 重新 add dict + dict check all
目标端"暂未接收"、站点接收字节 0 CPT 无数据可发(同上一行);或注册未完成 查 show connect 状态是否"注册"
目标端接收时间停滞 error_policy=0 因入库报错停链路;或磁盘 <10GB 反压 查 error table、stor;配 error_policy 后重启
装载报错"表已存在" 掩码带 CREATE 但目标已有表 去掉 CREATE 或用 DROP\|CREATE\|...
装载报错"模式不存在" 目标端未预建模式 目标库 CREATE SCHEMA "&lt;名>" AUTHORIZATION SYSDBA;
目标端表被手工删除后不同步 字典仍认为表存在,DML 全报错 alter exec_dm8 clear dict "&lt;SCH.TAB>" → 源端 add table "... DROP\|CREATE\|INSERT\|..."
数据重复 已一致的数据上又做了全量装载 该表 add table "... DROP\|CREATE\|INSERT\|..." 重装一次
链路延迟持续增大 目标端入库慢、线程不足、磁盘慢 查 show exec_dm8 thr、trx lag、stor;调 group 线程数
评论
后发表回复

作者

文章

阅读量

获赞

扫一扫
联系客服