异构数据同步踩坑记,聊聊金仓KFS是怎么解决数据一致性这个老大难的 先记一件旧事。前年一个国产化迁移项目Oracle迁金仓数据库存量KDTS、增量KFSKingbase FlySync电科金仓的异构数据同步软件链路跑了两个多月没出过事同步延迟长期稳定在几百毫秒。然后某天夜里财务说月报里一笔利息对不上两边差小数点后两位。我们查了两个小时业务代码一无所获。回头查数据才发现三天前有一条变更在目标端入库时撞上锁等待被跳过去了。差异在库里躺了三天没人知道。链路没断监控没报警但那个基本的问题答不上来两边的库此刻到底一不一致。本文记录的就是围绕这个问题的实践前半部分是我们手写的对账方案怎么一步步撞墙后半部分是KFS内置的校验修复怎么把这些问题逐一解决。代码都是当时的原稿做了简化。一、手写对账的三个版本1. count比对最初级的做法两边各数一遍行数-- 源端 Oracle SELECT COUNT(*) FROM biz_order WHERE create_time DATE 2025-06-01; -- 目标端 KingbaseES SELECT COUNT(*) FROM biz_order WHERE create_time DATE 2025-06-01;翻车很快。两边count都是8,324,117一条不差业务一跑就报错。排查发现有两千多条记录字段内容不一致。行数一致但内容不一致count完全看不见。这个阶段的认知是数数不叫校验。2. 聚合指纹第二版用MD5聚合值比对内容-- 两边各跑一遍比对 MD5 串 SELECT MD5(STRING_AGG( id::text || order_no || amount::text || status, , ORDER BY id)) FROM biz_order;能发现内容差异了但定位能力为零。指纹对不上只说明这张表有问题哪一行有问题不知道。要定位就得全表拉到应用层逐行比。几千万行的表比对脚本跑一次一个多小时而且源端业务不停比对期间新数据持续写入比完的区间随时可能又变了。等于打移动靶。3. Java分片对账同事写了第三版按主键分片拉到应用层比// 当时写的简化版对账逻辑现在看挺糙的 public ListLong compareRange(String table, long minId, long maxId) { ListLong diffIds new ArrayList(); long step 100_000; for (long start minId; start maxId; start step) { long end Math.min(start step, maxId); // 源端取这批数据的指纹 MapLong, String srcMap jdbcTemplate.queryForMap( SELECT id, MD5(concat_ws(|, id, order_no, amount, status)) FROM table WHERE id ? AND id ?, start, end); // 目标端取同一批 MapLong, String dstMap targetJdbc.queryForMap(/* 同样的SQL */); // 逐个比 for (Map.EntryLong, String e : srcMap.entrySet()) { String dst dstMap.get(e.getKey()); if (dst null || !dst.equals(e.getValue())) { diffIds.add(e.getKey()); } } } return diffIds; }这版勉强能用了但维护成本很高。表结构一变就得改代码。高峰期不敢跑怕影响生产库。还有个坑折腾了很久Oracle和KingbaseES对特殊字符的编码处理路径不同中文数据没问题碰到生僻字就报假差异。有一次对账跑了一夜报了三万多条差异两个人排查两天结论是其中99%是编码路径造成的假差异真差异只有十几条。假差异淹真差异比不校验还糟。这套工具后来还在用但它的能力边界大家都清楚了。二、KFS校验能力的逐项对照后来在另一个项目上把KFS的数据比对与修复模块完整用了一遍。它的整体思路和上面第三版Java工具是同源的分片、行级指纹、逐块比对。差别在于产品化程度。逐项说。粒度方面。KFS支持库级、模式级、表级、数据级四档。模式级文档里叫整模式校验最常用指定一个schema其下所有表自动纳入不需要逐表配置。我们当时拿一张有三百多张表的库试过配置只花了几分钟。日常巡检库级扫一遍账务重点表再单独加数据级校验这个组合用下来最顺手。分片方面。分片列推荐选选择性好的主键列整型和时间类型都支持片大小可配。有一点值得注意同一行数据始终落在同一个分片内比对两端切法一致不存在漏行。我们手写版是写死十万条一片遇到数据倾斜的大表性能就很差这个坑KFS用可配分片绕开了。MD5模式。逐行算指纹指纹不一致的行直接记录主键。比我们那个聚合指纹强的地方在于定位到行差异报告拿到手就知道该看哪条记录。增量校验。这是手写方案完全无解的部分增量数据每条都可能是差异不可能无限循环全量比对。KFS的做法是校验流跟随同步流每条变更写入目标端时同步生成列值哈希指纹和时间戳的组合标识标识本身就是比对依据全程不回查源端数据库。这一点有两个后果。其一校验对源端的干扰极小官方数据是对源端CPU负载的影响小于3%正常业务波动的噪声都比这个数大DBA不需要为校验调整容量规划。其二校验链路与同步链路相互独立跑校验不会拖慢同步。操作层面图形化路径是在同步管理平台KFSMC上建校验任务、关联调度计划命令行路径是配置table.properties后执行cmdcompare命令可以嵌进自动化运维脚本。两种方式覆盖同一套能力看团队习惯选。三、不停机校验与SCN前文的假差异问题根源是比对的两端取数时刻不一致。源端count是上午十点的数目标端count是十点零三分的数中间三分钟的增量正在路上数字对不上是正常的同步延迟不是数据不一致。KFS的解法是快照点。以Oracle到金仓的组合为例全量迁移完成时记录一个SCN号也就是Oracle内部的日志位点。校验任务直接指定这个SCN源端按该时间点的快照取数目标端比对同步落地的数据两端对的是同一时刻的账。移动靶变成静靶。配合差异数据二次校验流程完整了。第一轮全量比对报出的差异里可能混着同步延迟造成的假差异二次校验只针对差异记录重跑目标端追平校验期间的增量之后剩下的就是真差异才进入修复环节。整个二次校验在界面上就是差异结果处理里的一个选项2024年1月以后的版本支持只有主键表可用。一个实测数据浙江省人民医院LIS系统升级期间检验科反馈某批次报告状态异常运维用KFS增量校验排查17秒定位到原因是Oracle临时表残留数据干扰。此前同类问题的平均排查时间是6.5小时。差距主要在定位粒度报告直接给出表名、主键值、字段名和自己拉数据逐行啃是两种工作量。四、修复环节的CRUD对出差异后要把账平掉。我们当年的手写版长这样-- 1. 缺失的记录从源端补插 INSERT INTO kingdb.biz_order SELECT * FROM oradb.biz_orderdblink s WHERE s.id IN (SELECT id FROM diff_result WHERE diff_type MISSING); -- 2. 内容不一致以源端为准更新目标端 UPDATE kingdb.biz_order t SET (order_no, amount, status) ( SELECT s.order_no, s.amount, s.status FROM oradb.biz_orderdblink s WHERE s.id t.id) WHERE t.id IN (SELECT id FROM diff_result WHERE diff_type MISMATCH); -- 3. 目标端多出的记录删除 DELETE FROM kingdb.biz_order WHERE id IN (SELECT id FROM diff_result WHERE diff_type EXTRA);三段SQL增、改、删各一。写起来不难用起来全是问题dblink跨库性能差大事务容易锁表WHERE条件写错就是生产事故还必须挑窗口期执行。更实际的问题是这套流程没法全自动半夜跑完校验早上还得有人来执行修复自动化只完成了一半。KFS的修复分自动和手动两种模式。自动模式下校验任务关联修复策略确认差异后系统以源端为准做记录级修正缺的INSERT、错的UPDATE、多的DELETE即上述三段SQL的工作由系统完成无需人介入。解放军总医院的汇聚项目就是这个模式每天业务低谷时段自动校验当天增量、自动修复白天临床系统照常运行。手动模式则先出差异清单人工确认后再触发修复或只修指定记录。核心账务类表建议走手动机器改数之前留一道人工确认这个谨慎有必要。数据修复的正确形态就是CRUD但应该由机器执行人负责定规则、看报告。发现差异到修复完成的耗时从天级压到分钟级。五、项目数据几个公开项目的数据都做过核实。国家电网智慧计量。山东、河南两省计量实验室数据实时汇聚总部每天700GB增量延迟要求秒级。迁移环节由KDTS用9小时完成Oracle中间库6.8T存量搬迁KFS基于SCN衔接全量与增量。一致性保障采用自动定时校验加实时校验检测和修复全程无人工干预。海南移动故障管理系统。同城双中心按GB/T 20988-2007容灾标准最高第6级建设日均变更380G。灾备场景对一致性的要求高于普通同步平时不一致无人察觉真到灾难切换时灾备中心里是一份错账。KFS承担存量分块并行比对和增量实时校验双中心实测同步延迟亚秒级。解放军总医院医疗云。八个中心近400个系统HIS、LIS、PACS、EMR、体检、ICU全部纳入存量60TB以上日增量500GB、一亿多条时延小于1秒近四百条临床核心链路全程不停机建设。校验策略是每天低谷时段自动校验修复当天增量。临床数据对错误的容忍度极低这个机制在这里是刚需。三个行业互不相关做法完全一致校验交给调度修复交给策略人看报告。六、写在最后做国产化替代选型时同步性能很容易被摆在第一位跑分数据也确实直观。但从我们几个项目的经验看切换那天有没有底气取决于能不能随时证明两边数据一致。KFS把存量校验、增量校验、差异修复做成了内置能力校验过程不打扰生产对源端CPU影响不到3%这些能力的实际价值比吞吐量数字更直接。开头那笔差小数点后两位的利息后来是人工修的三个人查了半宿。如果当时有每天自动校验加自动修复那笔差异会在产生当晚被发现并修掉轮不到业务在三天后撞上。这就是我对这套机制的完整评价。