☰
Oracle迁移KingbaseES实战:KDTS工具与兼容性改造全记录
2026/10/20 7:23:50 网站建设 项目流程

干这行十多年,Oracle到国产数据库的迁移任务接过不少,但真正把 Oracle 12c 全量迁到人大金仓 KingbaseES V8.6,还是最近才完整跑通。工具用的是人大金仓官方自带的迁移工具 KDTS(Kingbase Data Trans Studio),也顺带处理了一批手工改写和兼容性适配的脏活。整个过程做下来,我的感受是:工具能解决大部分“搬数据”的问题,但迁移项目真正的难点,永远在搬完之后的应用适配。这篇文章就基于这个实操过程,把从评估、配置、执行、校验,到应用层改写和踩坑排查的完整链路都记录下来,给正在做国产化迁移评估或已经进场的 DBA、架构师、开发同学做个参考。

1. 转库前的准备工作与迁移方案评估

1.1 迁移工具选型:为什么我选了 KDTS

先回答一个最常见的问题:Oracle 转 Kingbase 一定得用官方工具吗?不一定,市面上有 Kettle、DataX、自研直连脚本等方式,但我的建议是,第一选择用官方迁移工具。

对比项KDTS 官方工具自研脚本 / JDBC直连DataX / Kettle 等ETL
对象迁移支持表、视图、序列、存储过程、触发器、同义词等都能覆盖基本只能搬表数据,结构要自己写主要做数据同步,复杂对象基本不适用
数据类型映射内置 Oracle 到 Kingbase 的映射规则,可手工调整自己写映射逻辑,工作量大映射规则通用,国产库特性支持弱
转换日志与报告生成对象迁移报告,逐条列出成功/失败项自己打日志有日志但对象兼容性判断要人工做
学习成本图形化界面,配置直观高中高,要理解 channel 和插件机制
回刷与增量处理支持任务重新执行和指定对象重迁自己控制数据同步可以做到准实时,但结构迁移帮不上忙

这个表列出来就能看出,KDTS 最核心的价值是“结构对象迁移 + 数据迁移”一体化的能力,而且它的迁移报告能直接告诉你哪些对象需要人工干预。对于 Oracle 12c 这种一堆存储过程、触发器、分区表的老库,用 ETL 工具只能搬数据,结构层面的兼容性判断你还得另写一套脚本去比对,等于多干一份活。

当时我们迁移的源库是某业务系统核心库,Oracle 12c 双节点 RAC,数据量不到 1TB,业务表 800 多张,另外还有 200 多个存储过程、几十个视图、少量物化视图和定时任务。这种规模如果用自研脚本,光结构迁移部分没有一周搞不定,还不算反复调试的时间。实际上用 KDTS,结构迁移和数据迁移加起来,一个工作日内跑完主流程是可行的。

1.2 迁移前的对象普查与兼容性预判

工具选好之后,别急着装。先花半天时间把源库的家底摸清楚,这会直接影响后面的迁移策略。

我在 Oracle 侧跑了一组查询,把评估对象分成了几类,这里直接列 SQL:

-- 查看业务用户下所有表的行数波动区间(抽样评估大表) SELECT table_name, num_rows, last_analyzed FROM all_tables WHERE owner = 'APP_SCHEMA' ORDER BY num_rows DESC; -- 统计大字段和分区表 SELECT table_name, column_name, data_type FROM all_tab_columns WHERE owner = 'APP_SCHEMA' AND data_type IN ('CLOB','BLOB') ; SELECT table_name, partition_count FROM all_part_tables WHERE owner = 'APP_SCHEMA'; -- 统计存储过程、函数、触发器、序列、同义词数量 SELECT object_type, COUNT(*) FROM all_objects WHERE owner = 'APP_SCHEMA' GROUP BY object_type ORDER BY 2 DESC;

为什么先跑这些?因为 KingbaseES V8.6 虽然提供了 Oracle 兼容模式,但“兼容”不代表“完全等价”。比如 Oracle 的 VARCHAR2 在非空约束下会把空字符串当作 NULL,Kingbase 的行为可能不同;又比如位图索引 Oracle 支持,Kingbase 需要手动调整为普通索引;再比如间隔分区、复合分区这类特性,迁移后可能需要改写或者降级为普通分区表。

另外,我习惯把全库的存储过程源码导出到本地,直接用 IDE 搜几个特征函数:DBMS_SCHEDULER、UTL_FILE、DBMS_LOCK、DBMS_ALERT、SYS_REFCURSOR、ROWNUM、CONNECT BY。这些基本就是迁移后必改的高频点。提前排查出来,就不至于到了转换报告出来才发现一片红。

1.3 目标端数据库初始化与兼容模式

目标端安装 KingbaseES V8.6 时,有个容易忽略但影响巨大的点:数据库初始化阶段的“兼容模式”。如果安装时没有选择 Oracle 模式,后面迁移进去的存储过程、函数、数据类型会有大量报错。

我的建议是,在做initdb或图形化安装选择模板库时,显式选择 Oracle 兼容模式的模板库(不同版本叫法可能有差异,有的叫“Oracle模式”,有的需要指定模板数据库,安装文档里都写得很清楚)。这一步和后面迁移是否顺畅强相关。

目标端还需要提前准备好表空间和迁移用户。演示中我建了一个专用表空间,并创建了与源业务用户同名的模式用户,这样迁移时对象归属关系更清晰,应用切换时改动也最小:

CREATE TABLESPACE tbs_app_data OWNER app_schema LOCATION '/kingbase/data/app_data'; CREATE USER app_schema WITH PASSWORD '请改成强密码' SUPERUSER; GRANT ALL PRIVILEGES ON TABLESPACE tbs_app_data TO app_schema;

需要注意,这里给迁移用户设置了超级用户权限,方便迁移过程中自动建表、建索引、建约束。如果是生产环境,我会建议迁移期间临时授权,迁移完成后再回收并收紧权限。

2. KDTS 迁移任务配置实战:从连接配置到对象勾选

2.1 源端 Oracle 连接参数与常见连接失败原因

打开 KDTS 后第一步是新建迁移任务,源库类型选 Oracle。这里需要填连接信息,最常见的形式是 JDBC URL 直连。

我当时源库是 Oracle 12c RAC 架构,配置如下:

  • 数据库类型:Oracle
  • 主机地址:192.168.x.x(RAC 的 SCAN IP)
  • 端口:1521
  • 服务名/数据库名:proddb(注意这里要填 Service Name,不是 SID)
  • 用户名/密码:迁移专用账号,不是业务账号本身

如果是 PDB 架构,比如 CDB 里挂着 PDB,那连接时要填 PDB 的 Service Name,而不是根容器 CDB 的 Service Name。最开始我们一位同事填了根库的 service name,连接测试一直报“ORA-01017: invalid username/password; logon denied”,这其实不是密码问题,而是连接到了错误的容器。

KDTS 客户端本身自带 Oracle JDBC 驱动,不需要在客户端机器上安装完整的 Oracle 客户端软件。但有个坑:源端防火墙必须放通 1521 端口,并且数据库的REMOTE_LOGIN_PASSWORDFILE相关设置不能影响远程连接。我在演示环境里把源库实例都正常运行,但如果源库处于mount状态,测试连接也会失败,这个容易让人误判。

连接测试成功后,KDTS 会读取源库的元数据,在对象列表里把表、视图、序列、函数、存储过程、触发器、同义词都列出来。这一步如果列表加载慢,多半是源库的dba_objects视图查询慢,不是什么工具 bug。

2.2 目标端 Kingbase 连接配置与迁移对象勾选

目标端配置比较简单,填 Kingbase 的连接信息:

  • JDBC URL:jdbc:kingbase8://192.168.y.y:54321/app_db
  • 用户名:app_schema
  • 密码:目标库密码

注意 Kingbase 默认端口是 54321,不是 5432。第一次连的时候我习惯先确认目标端kingbase.conf里的port参数,免得拿着默认端口去套。

接下来就是对象选择的环节。我的建议是:第一次不要全选,先勾“仅结构”跑一遍预迁移,把对象层面的兼容性摸底完成了,再跑“结构和数据”的全量迁移。原因是结构迁移失败会直接跳过数据迁移,如果一上来就全选,日志里会混着一堆结构失败导致数据未迁移的记录,排错成本很高。

我实际操作时把对象分成了三批:

  1. 第一批:基本结构对象——表、视图、序列、约束、索引。这一批跑完,库就“有架子”了。
  2. 第二批:逻辑对象——函数、存储过程、触发器、同义词。这一批是报错重灾区,需要逐个看转换报告。
  3. 第三批:数据。结构没问题了才开始搬数据。

还有一个细节:如果你只想迁业务表,不想迁日志表或中间表,可以在勾选时把这类表排除掉。演示环境里就有几张几百 GB 的归档日志表,业务上没必要迁到新库,直接排除,能省下不少时间。

2.3 高级选项与映射规则:批量提交、并行度、精度控制

KDTS 的高级选项里有两类参数直接影响迁移性能:

一是批量提交行数。默认是 500 行一批,但迁移大表时我习惯调整到 1000~2000 行。这个值不是越大越好——太大会拉长单批事务时间,目标端 WAL 膨胀,内存压力也上来;太小的坏处是交互次数多,整体吞吐上不去。比较稳的做法:小表用默认值,大表单独调高,分批跑。

二是并行度。KDTS 支持多个表并行迁移,也支持单表内分片并行。演示环境是一台 8 核 16G 的虚拟机,我没有把所有表都调成高并行,而是控制总并行度在 4 左右,避免 OOM。如果目标是物理机或者资源比较充足,并行度可以提高到 8。

字段数据类型映射默认是自动匹配的,但有几个点必须人工确认:

  • NUMBER 类型:Oracle 的NUMBER不带精度时,Kingbase 里推荐映射成NUMERIC,不要默认映射成DECIMAL(38,0),否则小数位会被截断。曾经遇到一个报表,金额字段本身是NUMBER,转换后直接变成整数,对账全错。
  • VARCHAR2(n):映射到VARCHAR(n)或CHARACTER VARYING(n)都能接受。但如果源库有中文数据,且目标库字符集是 UTF8,那么VARCHAR2(20)到底是按字节算还是按字符算,需要看两端配置,否则可能出现字段长度不足的报错。
  • CLOB/BLOB:自动映射问题不大,但大批量 CLOB 写入会显著拖慢迁移,最好单独一个批次跑,并且适当调大批量。

这里的核心原则是:不要完全相信自动映射,重点表的关键字段要人工过一遍映射结果。

3. 迁移执行中的观察点与数据校验方法论

3.1 结构迁移阶段:哪些对象会失败,哪些需要人工改写

结构迁移跑完后,KDTS 会生成一份迁移报告,按对象类型分组汇总成功率。我们在模拟项目 X 中遇到的情况比较典型:

  • 表结构、序列、索引、约束:成功率接近 100%。个别索引因长度问题报错,原因是 Kingbase 索引条目长度上限和 Oracle 不同,字符集叠加后超出了限制,需要改小索引列长度或改用函数索引/前缀索引。
  • 视图:大部分能自动转换,但带有CONNECT BY层级查询、ROWNUM分页、(+)外连接写法的视图,会挂红或转换结果需要人工检查。KDTS 能把外层语法改过来,但不代表逻辑等价。我自己遇到过一个视图里用了ROWNUM <= 10,转换后语义正确但性能极差,后来手动改成了窗口函数的写法,性能才恢复正常。
  • 存储过程/函数:这是重灾区。普通增删改查过程迁移成功率尚可,但只要用到 Oracle 特有的包或特性,就只能人工参与。比如UTL_FILE读写文件、DBMS_LOCK、DBMS_SCHEDULER、SYS_REFCURSOR动态游标,以及大量隐式类型转换,这些在 Kingbase 的 Oracle 兼容模式下部分有替代 API,部分需要重写逻辑。

迁移报告里每条失败记录都会附带转换日志,类似这样:

[ERROR] Function: GET_EMP_NAME, 转换失败, cause: 不支持函数调用: DBMS_UTILITY.GET_TIME [ERROR] Procedure: SYNC_DATA, 转换失败, cause: 语法不支持: MERGE INTO xxx [ERROR] Trigger: TRG_AUDIT_LOG, 转换失败, cause: 触发器事件不兼容: BEFORE INSERT ON table

我的工作习惯是:拿到报告后先按对象类型统计失败数量,再按失败原因归类。如果某类原因出现 20 次,就统一写一个改写模板,而不是一个对象一个对象地去翻代码。比如大量存储过程在EXECUTE IMMEDIATE里拼接了 Oracle 特有函数,那我可以先用正则批量替换公共模式,再逐个确认。

3.2 数据迁移阶段:大表与中断恢复

结构迁移干净后,开始数据迁移。KDTS 支持把对象任务拆成多个批次执行。我按表大小分了几个批次,小表合并跑,大表单独跑。执行过程中重点看两个指标:当前表的已迁移行数、迁移速度。

这里有个经验:迁移大表时,先把目标表的约束和索引全部跳过,等数据搬完再补建索引和约束。因为带着索引迁数据,每次提交都要同步更新索引,速度会差很多。更稳的做法是,在目标端先以无约束、无索引的堆表结构接收数据,全部写入完成后统一建主键、唯一约束和常用索引。这也能避免数据迁移过程中因为约束冲突导致任务中断。

中断恢复也是实际项目里绕不开的场景。有一次数据迁到一半源库那边有人误跑了批量更新,导致同一批数据的前后快照不一致。KDTS 的任务重跑机制可以基于对象级别重新执行,但不代表数据会自动做增量合并。稳妥的做法是:

  1. 数据迁移期间,源业务应用暂停写入,或者至少暂停和迁移表相关的写入。
  2. 如果不能完全暂停,就在迁移完成后,对最后时间窗口内的增量数据单独导一次(比如只导业务时间晚于迁移开始时间的数据)。
  3. 全量迁移完成后,再补做一次数据一致性比对。

另外,连接超时也是数据迁移阶段最容易遇到的问题。目标端kingbase.conf里的tcp_keepalives_idle和statement_timeout如果设置得太短,大批量写入期间连接可能被服务端杀掉。我习惯在迁移前把目标库的statement_timeout设为 0(关闭)或一个很大的值,迁移完成后再按业务要求设回去。这个细节来自一次真实踩坑:默认超时参数在大表迁移时频繁中断,日志里全是连接被终止的记录,当时还一度怀疑是网络问题。

3.3 迁移后的数据校验三板斧

数据迁移完,千万不能看一眼 KDTS 显示“任务成功”就认为大功告成。任务成功只能说明两边的行数在迁移完成那一刻是一致的,不能证明数据语义一致。我用的校验方法是三板斧:

第一板斧:行数校验。对每张表分别在源和目标执行SELECT COUNT(*),做一个自动化的对比脚本。这里提示一个小技巧,两张表聚合比对行数时,尽量用两张表同时取数,而不是先后取。因为先后取数的话,如果中间有增量写入,结果就不一致,最后还要花时间排查是不是迁移漏了。脚本大概长这样:

-- 源库 SELECT 'orders' AS table_name, COUNT(*) AS cnt FROM app_schema.orders UNION ALL SELECT 'user_accounts', COUNT(*) FROM app_schema.user_accounts; -- 目标库 SELECT 'orders' AS table_name, COUNT(*) AS cnt FROM app_schema.orders UNION ALL SELECT 'user_accounts', COUNT(*) FROM app_schema.user_accounts;

两边跑完直接人工或写个简单脚本比对输出。

第二板斧:抽样内容校验。行数一致不代表值一致。重点表要抽数据出来做内容比对,尤其是金额字段、状态字段、日期字段。我一般每个表抽 1000~5000 行,用主键关联,对比若干关键字段的哈希值。更直接的方法是对关键表做MIN(id)、MAX(id)、SUM(amount)的聚合对比,这种校验能在秒级发现“丢了数据”或“金额不一致”的问题。

第三板斧:业务试运行。找几条核心业务链路,直接在目标库跑一遍。比如查订单列表、做一次对账、执行一个存储过程。这一步能发现数据校验发现不了的兼容性问题,比如日期格式化规则差异、函数返回值和源库不一致。

4. 应用层适配与高频问题排查

4.1 应用 SQL 与存储过程重点改写清单

迁移完成只是“数据库层面”完成,应用层能不能跑起来是另一回事。KingbaseES 的 Oracle 兼容模式能消解掉大部分语法差异,但总有一些类型和语义差异需要改写。

就这次演示而言,应用层需要动手的地方集中在以下几类:

第一类:隐式类型转换。Oracle 允许某些情况下字符串和数字自动互转,但 Kingbase 的行为更严格。比如WHERE amount = '100',在 Oracle 里大概率能跑,Kingbase 里如果字段是数值类型,就可能报类型不匹配。这种不必全改,但应用新代码里建议直接写成WHERE amount = 100。

第二类:分页查询。老代码里常见ROWNUM BETWEEN 1 AND 20的写法,虽然 Kingbase 兼容模式下有函数和序列体系来模拟 rownum,但性能通常不理想。建议统一改成LIMIT ... OFFSET ...或窗口函数方式。这也是性能优化的一部分,不是单纯为了兼容性。

第三类:函数和包。存储过程和函数里用到 Oracle 特有包的场景,上面已经提到过。典型案例是定时任务:Oracle 里用DBMS_SCHEDULER创建的任务,迁移后需要转成 Kingbase 的 job 机制(比如通过扩展机制兼容CREATE JOB语法)。这类改写不能靠 KDTS 自动完成,需要应用开发介入。

第四类:自增列和序列。Oracle 12c 支持 identity column,Kingbase 也支持序列和自增列,但迁移后序列的当前值不会自动同步到历史数据的最大值。如果不处理,应用插入新数据时会报唯一键冲突。这个必须有一步“重置序列到当前数据最大值”的操作。

-- 假设表 app_schema.orders 的主键 id 使用序列 seq_orders_id SELECT setval('app_schema.seq_orders_id', (SELECT COALESCE(MAX(id),1) FROM app_schema.orders));

这个命令每条序列都要执行一遍,写个小脚本批量生成就行。

4.2 高频报错与解决记录

把这次迁移和过去几次国产化迁移里碰到的典型问题整理成一张速查表,按场景和报错分类:

报错或现象原因分析解决办法
连接源库报 ORA-01017连到了 CDB/PDB 错误的容器,或密码错误确认 URL 里填 PDB 的 Service Name,确认用户名密码
function xxx does not exist存储过程里调用了 Kingbase 不存在的函数查兼容函数列表,必要时新建同名自定义函数做桥接
中文字段乱码源库字符集与目标库字符集不一致迁移前统一源和目标库字符集,尽量都用 UTF8,并在 JDBC URL 指定编码
数据行数一致但金额对不上NUMBER 自动映射成整数类型引起精度损失迁移前人工调整映射规则,NUMBER 映射为 NUMERIC
大表迁移频繁中断目标库 statement_timeout 过短或网络不稳定临时调大 statement_timeout,分批迁移,禁用自动重试之外的人工干预
插入数据报唯一键冲突迁移后序列起点小于表内已有数据最大值用 setval 重置序列
视图/存储过程转换后逻辑异常工具转换语法不保证语义等价人工 review 高危对象,重点测试涉及金额、日期、层级查询的逻辑
索引创建报长度超限字符集和索引键长度共同导致减小索引列长度或改用哈希/前缀索引

这里要单独提一下中文乱码问题。它的隐蔽性在于:源库字符集如果是 ZHS16GBK,目标库是 UTF8,如果 JDBC 连接串上没有显式指定编码,读出来的中文字符串可能是正确的,写进目标库就变成乱码。而且肉眼看到乱码的时候,往往已经有一批数据写进去了。更早的规避方法是迁移前确认两端字符集能在链路上正确转换,用少量抽样表先试迁验证一下编码,再做全量。

4.3 上线前检查清单

迁移演示做到最后一步,必须把应用切到目标库。切换前,我习惯跑一遍检查清单防呆:

  • 对象完整性:表数量、视图、序列、索引、约束、存储过程数量是否与源库一致(结构迁移报告为准)。
  • 数据完整性:全表行数比对、抽样内容比对、关键业务试跑是否都通过。
  • 权限完整性:目标库中应用账号是否有足够的增删改查、执行存储过程权限。经常有项目迁移完数据一切正常,但应用访问报权限不足。
  • 统计信息:目标库所有迁移过来的表重新执行ANALYZE或VACUUM ANALYZE,否则优化器走错执行计划。
  • 回滚方案:保留源库只读状态,或者做一套“目标库切回源库”的演练。数据量越大,这个越重要。
  • 监控与基线:切换后记录关键业务的响应时间基线,和源库对比,尽早发现性能回退。

这份清单打印出来,逐项打勾,而不是拍脑袋觉得“应该没问题”。

我个人实际操作里的一点体会

最后聊点感受。KDTS 这类官方迁移工具,最大的价值是把“搬家和装修”的第一步自动化了,让我能把精力放在那些工具替代不了的地方——语义检查、性能调优、应用改造。不要期待任何工具按一个按钮就完成全部国产化迁移,架构层面的人为判断永远不可省。

真要给后来者一个建议的话:给自己多留出校验时间。数据迁移占用一天,校验和改写可能要占两三天。尤其是存储过程改写,很多时候不是语法不会写,而是业务逻辑有没有理解清楚。做迁移的 DBA 最好能和业务开发坐在一起过一遍核心过程,别只坐在终端前看日志。这是我做完这次迁移后最大的心得。

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询