那些年踩过的 MySQL 迁移坑,这次终于不用绕了
------聊聊新版数据库在 MySQL 兼容性上的一次真正升级
前段时间帮一个客户做数据库迁移,原本大家都觉得这是一次"按部就班"的工作。
业务系统是 Java Spring Boot,数据库用了很多年的 MySQL 5.7,整体架构也比较常见:MyBatis + Druid + HikariCP,十几个微服务,几百张业务表。
领导最开始给的目标很简单:
数据库替换掉,业务代码尽量不要动。
听起来很简单,但真正开始做之后才发现,真正耗时间的,从来都不是数据迁移。
而是兼容性。
很多人认为兼容,无非就是 SQL 能执行。
实际上,一个成熟系统真正依赖的,远远不止 SQL。
例如:
- JDBC Driver
- ODBC Driver
- JSON 函数
- 字符串函数
- ORM 框架
- Java API
- C/C++接口
- 存储过程
- 第三方中间件
这些地方,只要有一个地方不兼容,迁移成本都会直线上升。
最近看到 KES V9R3C18 发布,其中关于 MySQL 兼容能力 的升级,我觉得比很多宣传里的"支持XX语法"更值得聊,因为它解决的是迁移过程中最容易被忽略、也是最容易花时间的问题。
今天就结合自己做项目的一些经历,说说为什么真正的兼容,不只是SQL兼容。
很多人以为迁移改的是 SQL,其实改得最多的是外围
第一次接触数据库迁移的时候,我也以为:
SQL 能跑,就成功了一半。
后来发现完全不是。
真正花时间修改的,反而是这些东西。
例如 SpringBoot 的配置。
以前连接 MySQL:
properties
spring.datasource.driver-class-name=com.mysql.jdbc.Driver
如果数据库迁移之后,驱动不能继续使用。
意味着:
- 配置全部修改
- 打包重新发布
- 回归测试
- 运维重新部署
如果一个系统只有一个服务,那倒没什么。
如果有几十个微服务......
改一次配置,可能就是几十套环境一起发布。
真正费时间的不是改,而是测试。
所以很多迁移项目,最后都卡在连接层。
JDBC 才是真正影响迁移效率的地方
很多 Java 系统都有这样的代码。
java
Class.forName("com.mysql.jdbc.Driver");
Connection conn = DriverManager.getConnection(
url,
username,
password
);
这段代码可能已经跑了很多年。
如果数据库要求:
"驱动全部替换"
意味着:
- 所有项目重新编译
- 所有 SDK 更新
- Maven 重新发布
- 第三方组件重新验证
成本非常高。 
新版 KES V9R3C18 一个比较实用的升级,就是支持 MySQL 原生 JDBC Driver 直接连接。
这意味着很多项目:
连接方式不用改。
Driver 不用换。
代码不用重新适配。
对于存量项目来说,这一点比新增几个 SQL 语法更加实际。
因为真正影响项目周期的,很多时候不是 SQL,而是部署。
ORM 框架其实比 SQL 更挑数据库
很多人写 SQL。
真正上线以后,SQL 都是 ORM 自动生成。
例如 MyBatis。
Hibernate。
JPA。
这些框架生成出来的 SQL,并不是人工写的。
例如分页:
sql
SELECT *
FROM user_info
LIMIT 20 OFFSET 100;
排序:
sql
SELECT *
FROM orders
ORDER BY create_time DESC;
批量插入:
sql
INSERT INTO user_info(name,age)
VALUES
('Tom',18),
('Lucy',20),
('Jack',30);
如果数据库只是"大部分兼容"。
ORM 很容易生成一些边界 SQL。
开发根本不会发现。
直到线上。
所以真正成熟的数据库兼容,不只是支持几百条 SQL。
而是能够覆盖:
- DDL
- DML
- DQL
- ORM 自动生成 SQL
新版资料里面提到:
99% 常用 MySQL 语法兼容。
我觉得这个数字本身不是重点。
重点是:
覆盖的是业务真正会用到的语法,而不是实验室里的 SQL。
JSON 已经成为现代业务最难兼容的一部分
现在很多互联网业务,都越来越喜欢把扩展字段放进 JSON。
例如订单。
json
{
"coupon":100,
"vip":true,
"channel":"wechat"
}
SQL 经常这样写:
sql
SELECT
JSON_EXTRACT(ext,'$.coupon')
FROM orders;
或者:
sql
SELECT
JSON_SET(
ext,
'$.vip',
true
)
FROM orders;
如果 JSON 函数行为不一致。
迁移以后:
最可怕的不是报错。
而是结果变了。
例如:
- NULL 返回不同
- 类型转换不同
- JSON Path 不一致
- 优先级不同
这些问题很难测试出来。
新版 KES 在这次升级里,把 JSON 函数及 JSON 操作兼容能力 做了进一步增强,这一点我认为比新增几个字符串函数更重要。
因为现在越来越多业务已经开始把 JSON 当成半结构化数据来使用。
兼容得越完整,迁移风险越低。

字符串函数,看起来简单,其实最容易踩坑
很多系统都有类似写法:
sql
SELECT
CONCAT(first_name,last_name)
FROM employee;
或者:
sql
SELECT
SUBSTRING(name,1,5)
FROM product;
还有:
sql
SELECT
REPLACE(phone,'-','')
FROM customer;
这些函数每天执行成千上万次。
如果返回规则稍微有一点区别。
整个系统都会出现:
- 查询异常
- 排序异常
- 模糊匹配异常
很多开发觉得:
"字符串函数还能有啥区别?"
实际上,不同数据库对于:
- NULL
- 空字符串
- 字符集
- 长度计算
处理方式都有细微差异。
真正迁移的时候,这类问题远比 SQL 是否能执行更难发现。
新版 KES 提到常见字符串函数能够做到输出结果保持一致,这种一致性,对于业务稳定运行,比新增几个高级特性更有价值。