MySQL迁移至人大金仓(KingbaseES)兼容方案

前言

下载地址

https://download.kingbase.com.cn/xzzx/index.htm

金仓数据库管理系统KingbaseES V9是企业级大型通用融合数据库产品

  • 面向全市场,具备三种兼容模式,最新发布版本为 V009R001C002B0014

  • 面向细分市场,高度兼容MySQL,最新发布版本为 V009R003C011

  • 面向细分市场,高度兼容SQLServer,最新发布版本为 V009R004C011

如果项目本身使用的Mysql想切换为KingbaseES版本选择:

V009R003是比V009R001的Mysql模式对Mysql的兼容性更好的。

如果项目使用V009R001就没啥问题建议使用V009R001,他是主分支使用的用户会多点,如果不兼容的地方太多则可以考虑V009R003版本。

如果使用特别多MySQL的函数建议用V009R003,他对MySQL的兼容性较好。

就算是V009R003也不是完全兼容MySQL的所有函数。

SQL兼容

确定人大金仓版本,不同版本间区别较大,不完全兼容。

查看版本

1
select version();

v8版本无法使用auto_increment自增,需要使用serial,同时迁移工具无法转换。
迁移工作开始前一定要确定数据库版本!

查询剩余有效期

1
select GET_LICENSE_VALIDDAYS();

类型

MySQL中的int数据不要勾选无符号,这个类型在迁移的时候目标格式会变成unit4而不是正常的integer,从而导致后台类型映射有问题。

image-20250221170100757

时间 SYSDATE

在 MySQL 中要使用 SYSDATE(),在人大金仓中使用 SYSDATE

结果

可以使用 NOW(),他在MySQL和人大金仓里都能用。

时间差

Mysql

计算方式是后面减去前面

1
SELECT timestampdiff(MINUTE,'2025-02-20 14:05','2025-02-20 17:05');

这个在V009R003中是有的,在V009R001的Mysql模式中没有。

人大金仓

计算方式是前面减去后面

1
SELECT AGE('2025-02-20 14:05','2025-02-20 17:05');

结果

暂时未找到两者都兼容的语法。

Mysql的timediff和人大金仓的AGE函数作用是一样的,这个函数在人大金仓中是没有的。

1
SELECT timediff('2025-02-20 14:05','2025-02-20 17:05');

字符串兼容

在Kingbase数据库中查询字符串类型数据时用的是单引号来查询,而在MySql和Oracle中可以用双引号或者单引号。

为了保证 SQL 语句在 Kingbase、MySQL、Oracle 等不同数据库间的兼容性,建议统一使用单引号来表示字符串常量。

结果

因为单引号是 SQL 标准中表示字符串的方式,在各个数据库中都能正常使用。

group by聚合函数

Kingbase里group by的字段必须要在Select中,而Mysql没有限制。

开启宽松模式可以突破 GROUP BY 字段必须在 SELECT 列表中的限制。

关键字

level、year、ctid

比如下面的两种写法是报错的

1
2
SELECT 2025 year;
SELECT 1 level;

可以修改为如下形式

1
2
SELECT 2025 `year`;
SELECT 2025 as year;

区分大小写

1
select * from t_user where binary loginname='90006';

目前没有两个都兼容的方式 可以先把binary去掉

1
select * from t_user where loginname='90006';

打开宽松模式

方式1(推荐)

查询

1
2
-- 查询 sql_mode 系统变量的值
show sql_mode;

修改配置

1
2
3
4
5
6
7
8
-- 修改全局的 sql_mode 配置
ALTER SYSTEM SET sql_mode = '';

-- 重新加载配置文件,使修改生效
SELECT sys_reload_conf();

-- 查询 sql_mode 系统变量的值
show sql_mode;

使用 ALTER SYSTEM 会修改配置文件,通过 SELECT sys_reload_conf(); 会加载配置文件使配置生效,是永久修改数据库全局配置的方式。

也可以修改成默认

1
ALTER SYSTEM SET sql_mode = 'ONLY_FULL_GROUP_BY,ANSI_QUOTES';

说明

ONLY_FULL_GROUP_BY

ONLY_FULL_GROUP_BY是一种 SQL 模式设置,用于严格限制在使用GROUP BY子句时的查询行为。

当启用ONLY_FULL_GROUP_BY模式时,意味着在SELECT列表中出现的非聚合列必须同时出现在GROUP BY子句中,否则查询会报错。

ANSI_QUOTES

  • 含义ANSI_QUOTES模式主要用于控制对字符串和标识符的引号处理方式。

    当启用ANSI_QUOTES模式时,双引号(")将被用于标识标识符(如表名、列名等),而单引号(')用于表示字符串常量。

  • 目的和作用:这种设置的主要目的是遵循 ANSI SQL 标准,使数据库的行为与标准 SQL 更兼容,便于在不同的数据库系统之间进行移植和交互操作。

    在使用一些需要严格遵循 ANSI 标准的应用程序或工具时,启用ANSI_QUOTES模式可以确保查询的正确性和兼容性。

  • 示例:在创建表时,如果启用了ANSI_QUOTES模式,

    可以使用双引号来指定表名或列名中的特殊字符或保留字,如:CREATE TABLE "my_table" ("id" INT, "name" VARCHAR(50));

    在查询中,字符串值必须使用单引号,如:SELECT * FROM "my_table" WHERE "name" = 'John';

方式2

修改配置文件

查询

1
2
-- 查询 sql_mode 系统变量的值
show sql_mode;

如果内容是空则开启了宽松模式

配置文件路径

1
cd /data/db/Kingbase/data

修改kingbase.auto.conf

1
sql_mode = ''

重启

1
2
3
service kingbased stop
lsof -i:54321
service kingbased start

连接方式

jar文件在Kingbase/Interface/jdbc

1
mvn install:install-file -DgroupId=com.kingbase -DartifactId=kingbase8 -Dversion=9.0.0 -Dfile="D:\Jars\kingbase8-9.0.0.jar" -Dpackaging=jar -DgeneratePom=true

pom.xml

1
2
3
4
5
<dependency>
<groupId>com.kingbase</groupId>
<artifactId>kingbase8</artifactId>
<version>9.0.0</version>
</dependency>

连接字符串

1
jdbc:kingbase8://xxxx:54321/xhkjedu_school_test?currentSchema=xhkjedu_school_test

客户端

SQLynx

https://www.sqlynx.com/zh-cn/download/

官方

https://download.kingbase.com.cn/xzzx/index.htm

注意

比如SELECT 2025 year;是在人大金仓中会报错,但是使用SQLynx连接人大金仓却能正常执行,在官方客户端中是报错的。所以测试建议使用官方的客户端。

迁移报错

如果报错

Caused by: com.kingbase8.util.KSQLException: ERROR: invalid byte sequence for encoding “UTF8”: 0x00

解决方法

image-20250303151349032