随着国家信创战略的深入推进,我司核心业务系统需要进行全面的国产化改造。原系统基于MySQL数据库构建,已稳定运行5年,数据量达到TB级别,包含数百张业务表和大量存储过程。根据企业技术栈国产化要求,需要将数据库迁移至国产金仓数据库(KingbaseES)平台。
选择使用KDTS理由:
Kingbase Data Transfer System(KDTS)是金仓数据库官方提供的专业数据迁移工具,主要功能包括:
-
多源数据库支持
-
全对象迁移能力
-
智能转换特性
-
高效迁移引擎
接下来是我在迁移过程中遇到的一些报错以及处理方式:

进行查看日志:
报错1:分区键表达式函数问题
fail:
com.kingbase8.util.KSQLException: ERROR: functions in partition key expression must be marked IMMUTABLE


根据错误信息,com.kingbase8.util.KSQLException: ERROR: functions in partition key expression must be marked IMMUTABLE,问题出在分区键表达式中使用的函数 unix_timestamp 没有被标记为 IMMUTABLE。IMMUTABLE 表示该函数在给定相同输入时总是返回相同的结果,且不会修改数据库状态。
在 Kingbase 中,分区键表达式中的函数必须是 IMMUTABLE 的,而 unix_timestamp 函数可能被标记为 STABLE 或 VOLATILE,因此无法直接用于分区键。
解决方案
使用 EXTRACT 函数: 你可以使用 EXTRACT 函数来提取时间戳的秒数,EXTRACT 函数是 IMMUTABLE 的。
PARTITION BY RANGE (EXTRACT(EPOCH FROM created_date))
点击保存,并执行:


可以看到问题已解决。
报错2:嵌套语法不兼容
报错信息:
fail:
com.kingbase8.util.KSQLException: ERROR: syntax error at or near ")"
Position: 367 At Line: 1, Line Position: 367
问题出在JOIN语法上,金仓数据库不支持这种嵌套括号的JOIN写法。
处理方法:
新库处理,单独更新脚本执行即可。
CREATE VIEW tablename123 AS
SELECT
a.id AS item_id,
a.item_name AS item_name,
b.id AS rule_id,
b.rule_name AS rule_name,
b.value AS value,
b.tenant_id AS tenant_id,
c.factor_name AS factor_name,
d.factor_value AS factor_value
FROM atl_config_item a
INNER JOIN tablename123 b ON a.id = b.config_item_id
INNER JOIN tablename12345 c ON a.id = c.config_item_id
INNER JOIN tablename123123445 d ON d.config_rule_id = b.id AND d.config_rule_factor_id = c.id
ORDER BY a.id, d.config_rule_id, d.config_rule_factor_id;
报错3:字符集编码问题#手工处理
报错信息:
fail:
com.kingbase.kdts.g.b: Failed to write table data! , datas:
Caused by: com.kingbase.kdts.writer.b.a: java.io.IOException: Ending write to copy failed.
Caused by: java.io.IOException: Ending write to copy failed.
Caused by: com.kingbase8.util.KSQLException: ERROR: invalid byte sequence for encoding "UTF8": 0x00
Where: COPY tabletest1, line 244, column relevance_key
---处理过程,mysql进行输出为csv格式
mysql> SELECT * INTO OUTFILE '/data/mysql/tabletest1_hex.csv' FIELDS TERMINATED BY ',' ENCLOSED BY '"' LINES TERMINATED BY '\n' FROM tabletest1;
Query OK, 244 rows affected (0.01 sec)
----Kingbase 层操作copy:
cd /home/kingbase
root@VM-10-12-ubuntu:/home/kingbase# cp /data/mysql/tabletest1_hex.csv .
----执行copy命令:
kingbase@VM-10-12-ubuntu:~$ ksql -U system -d wsedtd -h 192.168.10.12 -p 54321 -c "COPY tabletest1 (id,***********) FROM '/home/kingbase/tabletest1_hex.csv' WITH (FORMAT csv, DELIMITER ',',FORCE_NULL (relevance_key),ENCODING 'UTF8');"
Password for user system:
ERROR: invalid byte sequence for encoding "UTF8": 0x00
CONTEXT: COPY tabletest1, line 1
##提示报错:进行替换处理:
sed 's/\x00//g' /home/kingbase/tabletest1_utf8.csv > /home/kingbase/tabletest1_clean.csv
#然后再次进行copy操作:
kingbase@VM-10-12-ubuntu:~$ ksql -U system -d wsedtd -h 192.168.10.12 -p 54321 -c "COPY tabletest1 (id,***********) FROM '/home/kingbase/tabletest1_clean.csv' WITH (FORMAT csv, DELIMITER ',', ENCODING 'UTF8');"
Password for user system:
ERROR: invalid input syntax for type numeric: "\N"
CONTEXT: COPY tabletest1, line 1, column company_id: "\N"
#根据上边报错,再次进行替换处理
sed -i 's/\N/NULL/g' /home/kingbase/tabletest1_clean.csv
#然后再次进行copy操作:
kingbase@VM-10-12-ubuntu:~$ ksql -U system -d wsedtd -h 192.168.10.12 -p 54321 -c "COPY tabletest1 (id, **************) FROM '/home/kingbase/tabletest1_clean.csv' WITH (FORMAT csv, DELIMITER ',', ENCODING 'UTF8');"
Password for user system:
ERROR: invalid input syntax for type numeric: "NULL"
CONTEXT: COPY tabletest1, line 1, column company_id: "NULL"
#根据上边报错,再次进行替换处理
sed -i 's/NULL//g' /home/kingbase/tabletest1_clean.csv
#然后再次进行copy操作:
kingbase@VM-10-12-ubuntu:~$ ksql -U system -d wsedtd -h 192.168.10.12 -p 54321 -c "COPY tabletest1 (id,****************) FROM '/home/kingbase/tabletest1_hex_clean.csv' WITH (FORMAT csv, DELIMITER ',', ENCODING 'UTF8');"
Password for user system:
ERROR: invalid input syntax for type bytea
CONTEXT: COPY tabletest1, line 244, column relevance_key: "\0"
#根据上边报错,再次进行替换处理
sed -n '244p' /home/kingbase/tabletest1_hex_clean.csv
"1129651325741506594","943460702762700801","12","","","","","CAROUSEL_LIST","","","���表","","","7","WORK","","","","","2025-04-22 16:33:39","2025-04-22 16:33:39","ONLINE","","","","MOBILE","","","","","","\0","","",""
根据上边信息查看报错内容,再次进行替换
sed -i 's/\0//g' /home/kingbase/tabletest1_hex_clean.csv
#然后再次进行copy操作:
kingbase@VM-10-12-ubuntu:~$ ksql -U system -d wsedtd -h 192.168.10.12 -p 54321 -c "COPY wsedtd.tabletest1 (id,***********) FROM '/home/kingbase/tabletest1_hex_clean.csv' WITH (FORMAT csv, DELIMITER ',', ENCODING 'UTF8', FORCE_NULL (relevance_key));"
Password for user system:
COPY 244
###执行成功,数据正常同步至数据库。
问题4:#外键非空缺失依赖
报错信息:
wsedtd.tabletest22 fail:
com.kingbase8.util.KSQLException: ERROR: insert or update on table "tabletest24" violates foreign key constraint "tabletest22_3BE15C83"
Detail: Key (company_id)=(2) is not present in table "tabletest25".
wsedtd.tabletest23 fail:
com.kingbase8.util.KSQLException: ERROR: insert or update on table "tabletest26" violates foreign key constraint "tabletest23_56F7617"
Detail: Key (cost_id)=(39) is not present in table "art_cost_center_item".
wsedtd.fk_user_cost_center_item_user_id fail:
com.kingbase8.util.KSQLException: ERROR: insert or update on table "tabletest26" violates foreign key constraint "cost_id_2BB897"
Detail: Key (user_id)=(47) is not present in table "tabletest27".
在 tabletest26 表上添加一个外键约束,
引用 tabletest27 表的 id 字段,
但是 tabletest26
表中存在一些记录(如 user_id=47),这些记录的 user_id 值在 tabletest27 表中找不到对应的记录
mysql> SELECT user_id
-> FROM wsedtd.tabletest26
-> WHERE user_id NOT IN (
-> SELECT id
-> FROM wsedtd.tabletest27
-> );
±--------+
| user_id |
±--------+
| 208 |
| 47 |
| 132 |
±--------+
3 rows in set (0.00 sec)
然后进行数据处理。再次执行,即可修复。
问题5:#视图报错处理函数不支持
报错信息:
test123.tabletsts28 fail:
com.kingbase8.util.KSQLException: ERROR: function sys.timestampdiff(unknown, text, text) is not unique
Hint: Could not choose a best candidate function. You might need to add explicit type casts.
Position: 787 At Line: 1, Line Position: 787
原因:
使用Kingbase8/PostgreSQL支持的日期运算语法
避免使用可能不兼容的函数
问题6:#语法差异问题
报错信息:
ERROR: column "f.scene_id" must appear in the GROUP BY clause or be used in an aggregate function
Position: 768 At Line: 1, Line Position: 768
改写SQL:
完整的GROUP BY:添加了所有SELECT中非聚合列到GROUP BY子句
语法修正:修复了所有括号匹配问题
格式优化:改进了SQL格式,使其更易读
函数一致性:统一了IF函数的使用方式
问题7:#语法兼容性差异问题
test123.tabletsts29 fail:
com.kingbase8.util.KSQLException: ERROR: invalid reference to FROM-clause entry for table "r"
Hint: There is an entry for table "r", but it cannot be referenced from this part of the query.
Position: 88 At Line: 1, Line Position: 88
错误位置:
where (test123.r.reimb_status > '1004')
问题出在 test123.r 的引用方式。
在 SQL 中,表别名(如 r)的作用是简化表名引用,不需要也不能用 schema(test123)修饰别名
兼容性问题:
某些数据库(如 MySQL)可能允许这种写法,但 Kingbase 严格遵循 SQL 标准,不允许用 schema 修饰别名。
总结:
KDTS工具针对同步过程中,出现的问题可以进行单独处理,大大方便了提升效率,同时也把自己迁移过程中的问题记录,分享给大家,希望对大家有帮助。