当前位置: 首页 > news >正文

MySQL迁移Kingbase?一文告诉你有哪些语法兼容的坑

信创浪潮下,“MySQL & Oracle 兼容”是很多国产数据库厂商的标配宣传语,但兼容到什么程度、哪些细节会踩坑,往往只有真刀真枪的测过才知道。语法层面能跑通不代表业务逻辑能对齐,一个 REPLACE INTO 的主键校验差异,或者某些函数的执行结果不符合预期,都有可能在生产环境酿成事故。

本文以 Kingbase V9 为例,从多个维度验证其与 MySQL 在语法、函数等方面的实际表现,供各位朋友参考。

KingbaseES V009R001C010 MySQL 8.4.7 OS Linux 7.9

语法兼容测试

SQL 语法兼容性

Kingbase V9 支持show create table的方式获取具体的创建表 SQL,

但不支持通过show index from语法获取索引信息,

仍然需要通过传统的\d方式。

SHOW DATABASES/SHOW TABLES/SHOW VARIABLES/SHOW ENGINES等语法都不支持,好在是 Kingbase 中获取这类信息的方式也足够简便,并不会影响到实际的使用体验。

数据类型兼容性

MySQL 中常见的数据类型在 KingbaseV9 中都能够支持,类似 ZEROFILL 等极少部分特殊用法不支持。

对于数值类型的边界和枚举类型中的未知字符都能够很好的识别。

DML 兼容性测试

DML 兼容性测试中主要验证 MySQL 中比较特殊的 DML 用法,绝大多数常用的场景都是兼容的。

例如,INSERT IGNORE INTO 测试,Kingbase 和 MySQL 的预期结果一致。

但是在 REPLACE INTO 中却表现出了不同的结果,

CREATE TABLE t_replace (id INT PRIMARY KEY, sku VARCHAR(20) UNIQUE, stock INT); INSERT INTO t_replace VALUES (1, 'A001', 100); REPLACE INTO t_replace VALUES (1, 'A001', 200); REPLACE INTO t_replace (sku, stock) VALUES ('A001', 50); SELECT * FROM t_replace;

这段代码中的第二条 REPLACE INTO 语句,在 MySQL 中因为缺少主键没有能执行成功,但在 KingbaseV9 中却直接忽略主键更新了其中的数据,导致两者结果不一致。

这里不深究两者实现上的底层逻辑,因为是测试 Kingbase 对于 MySQL 的兼容性,那么我认为这个场景是不符合预期的。

如果说上述结果有可能只是设计逻辑上的差异,那么接下来的这段测试结果就更加让人摸不着头脑。

CREATE TABLE t_replace (id INT PRIMARY KEY, sku VARCHAR(20) UNIQUE, stock INT); INSERT INTO t_replace VALUES (0, 'A000', 100); INSERT INTO t_replace VALUES (1, 'A001', 100); INSERT INTO t_replace VALUES (2, 'A002', 100); REPLACE INTO t_replace VALUES (1, 'A001', 200); REPLACE INTO t_replace (sku, stock) VALUES ('A001', 50);

没有详细分析具体的原因,MySQL 是 InnoDB 引擎,对于 update 采用的是原值更新的方式;而 Kingbase 的更新采用的是“版本追加”的方式,更新前后的数据都存在,通过事务 ID 来控制数据是否可见。猜测可能是由于版本控制上的异常导致这种情况的发生。

函数兼容测试

NULL 值处理测试

NULL 在数据库中是个特殊的数据,不同的数据库对于 NULL 值的处理常常有一定的差别。

测试结果倒是让我有些意外,本以为两者之间会有比较大的差异,测试下来发现 IFNULL、COALESCE、LOCATE、SUBSTRING_INDEX、GROUP_CONCAT 等函数在处理空值的行为都是一致的。

但是也遇到了一个特殊情况, 在使用 SELECT LPAD(‘ab’, 5, ‘’); 进行填充测试的时,MySQL 返回的是空值,而 Kingbase 则返回的是 ‘ab’ 字符。

比较奇怪的是,两者在处理 NULL 和 ‘’ 值的行为是一致的,为什么会出现上图的现象,有机会向 Kingbase 的开发人员讨教一二。

开窗函数兼容测试

开窗函数中大部分的语法都是兼容的,但是在 LAG 函数上有些差异。

CREATE TABLE t_sales ( id INT PRIMARY KEY, dept VARCHAR(10), emp_name VARCHAR(20), salary DECIMAL(10,2), sale_date DATE ); INSERT INTO t_sales VALUES (1, 'A', 'Tom', 8000, '2026-01-05'), (2, 'A', 'Jerry', 9000, '2026-01-10'), (3, 'A', 'Anna', 9000, '2026-01-15'), (4, 'B', 'Mike', 7000, '2026-01-08'), (5, 'B', 'Lucy', 7500, '2026-01-12'), (6, 'B', 'John', 6000, '2026-01-20'); -- 测试SQL1 SELECT dept, emp_name, sale_date, salary, LAG(salary, 1) OVER (PARTITION BY dept ORDER BY sale_date) AS prev_salary, LEAD(salary, 1) OVER (PARTITION BY dept ORDER BY sale_date) AS next_salary FROM t_sales; -- 测试SQL2 SELECT dept, emp_name, sale_date, salary, LAG(salary, 1, 0) OVER (PARTITION BY dept ORDER BY sale_date) AS prev_salary, LEAD(salary, 1, 0) OVER (PARTITION BY dept ORDER BY sale_date) AS next2_salary FROM t_sales;

上述测试 SQL1 的预期结果是,按照 sale_date 排序后,每行取同 dept 内上一条/下一条的 salary,第一行的 prev_salary 和最后一行的 next_salary 均为 NULL。两库的测试结果均符合预期。

测试 SQL2 的预期结果是,如果 prev_salary 的前值和 next_salary 的后值为空的情况下,取其默认值。

这个测试中,MySQL 的结果是符合预期的;

但 Kingbase 直接报错了,从报错信息上看应该是参数上的错误。

从 Kingbase 官网上的文档看,LAG 函数是支持默认值参数的,而且根据官方给出的测试案例也是能够执行成功的,具体的文档参考 https://docs.kingbase.com.cn/cn/KES-V9R1C10/application/application-develop-guide/reference/mysql/functions_operators/window_functions#lag。为什么上述的测试 SQL2 会报错,也希望能够得到 Kingbase 开发人员的分析和解释。

JSON 函数测试

JSON 支持也是各大数据库重点宣传的功能之一,因此这里将 JSON 单列出来进行测试。

常规的插入和更新操作,Kingbase 和 MySQL 的预期行为一致,数据更新和插入过程中都会严格验证是否符合 JSON 语法,对于错误的数据是不允许插入的。

同时对于更高阶的嵌套路径访问和数组下标访问等场景,两个数据库表现出来的结果均符合预期。

CREATE TABLE t_json ( id INT PRIMARY KEY, data JSON ); INSERT INTO t_json VALUES (1, '{"name":"Tom","age":20,"tags":["a","b","c"],"addr":{"city":"Hangzhou","zip":"310000"}}'), (2, '{"name":"Jerry","age":25,"tags":["b","d"],"addr":{"city":"Shanghai","zip":"200000"}}'), (3, '{"name":"Anna","age":null,"tags":[],"addr":null}'); -- '->'和'-->'操作符 -- 预期: raw_name带双引号 "Tom",unquoted_name不带引号 Tom(->>相当于JSON_UNQUOTE(JSON_EXTRACT(...))) SELECT id, />

和在 MySQL 中的执行结果是一致的。

写在最后

从总体测试结果来看,Kingbase V9 和 MySQL 的兼容性还是非常不错的,绝大部分的 SQL 语法和函数都不需要任何改造,可以直接使用。

不过对于一些特殊的用法,尤其是 MySQL 特有的“方言”的使用上,有些部分还是存在一些差异的。这也提醒我们数据库的迁移改造需要经过严格的测试验证,不要等到上线后发现问题再去调整。

最后声明一点,虽然在这篇文章里列举了不少兼容性上的差异,是因为对于预期结果一致的部分一笔带过了,仅仅将差异部分记录了下来。

http://www.cnnetsun.cn/news/3526044.html

相关文章:

  • Loritta快速入门:5分钟搭建你的第一个Discord机器人
  • Injector命令行参数全攻略:从基础到高级用法,开发者必备清单
  • Windows本地部署Qwen2大模型|超详细步骤,附带全套避坑清单(新手零门槛)
  • 大模型AI搜索信源排名规则深度解析:豆包 vs DeepSeek 引用逻辑对比与GEO实战策略
  • AMD Qwen3.5-9B-w4a16-tao-symgroup-torchao-v0.17.0社区贡献指南:如何参与模型优化与改进
  • 如何为iOS 17设备解锁JIT编译能力:SideJITServer实战指南
  • DeepSeek LeetCode 3605. 数组的最小稳定性因子 Rust实现
  • 新手小白学C语言——排序算法(冒泡、选择、插入)
  • HTTP和HTTPS
  • AI会话越多越忙?搭建首个自改进业务代理团队的完整实践
  • 微信支付证书自动化管理:Java平台证书下载工具深度解析
  • Relative Rotation Graph(相对旋转图)|Highcharts创建RRG 图示列代码
  • Aperture多语言SDK使用教程:Go、Java、Python、JavaScript全攻略
  • Golang学习-sync.RWMutex 读写锁
  • 物理AI迎来“开悟时刻”:大晓发布开悟世界模型、以人为中心的环采方案2.0与三大行业解决方案
  • 炸裂!WhatsApp再诉NSO:一纸“永久禁令”为何沦为废纸?全球“合法监听”黑产链调查
  • 金额用 Long 还是 BigDecimal?
  • grunt-contrib-copy 配置文件详解:从基础配置到高级选项
  • 【限时解密】头部MCN私有数字人直播中台架构图:含ASR延迟<200ms的FPGA加速方案与商用授权清单
  • fluxsort基准测试:在不同数据集上的表现分析
  • KnpGaufretteBundle社区贡献指南:如何参与项目开发与维护
  • Bazel rules_foreign_cc快速入门:5分钟学会构建外部C/C++项目
  • Verilog飞行射击游戏设计与实现:从敌机生成到子弹碰撞
  • 程序员誓言Programmer‘s Oath:保护用户隐私的7个关键原则
  • kableExtra在企业级应用中的应用:构建自动化报表系统的完整方案
  • ES6-learning:模块化编程的终极指南 - 掌握现代JavaScript开发的核心技能
  • McBSP多通道选择与帧同步:TDM通信原理与实战配置详解
  • physx-rs源码探秘:Rust绑定NVIDIA PhysX的实现原理
  • Slug性能优化技巧:提升URL短链服务响应速度的10个方法
  • 英雄联盟Akari助手:免费开源的终极游戏效率工具,快速提升你的操作水平