🤖
AI审核中

MySQL8.0退场之后:Java项目该如何选择8.4LTS与9.7LTS

Java 27分钟 120浏览 1评论

很多 Java 项目的技术栈已经更新了好几轮。

JDK 从 8 升到了 17、21,Spring Boot 从 2.x 升到了 3.x 甚至 4.x,Redis、Nginx、Docker 镜像也在不断更新。

但打开数据库服务器,可能仍然会看到一个非常熟悉的版本:

MySQL 8.0。

过去这并没有什么问题,MySQL 8.0 长期承担着大量生产系统的主力数据库角色。

但到了 2026 年,这件事情已经发生变化。

Oracle 官方明确说明:从 2026 年 4 月发布 MySQL 8.0.46 开始,MySQL 8.0 正式到达 End of Life。 官方同时建议 MySQL 8.0 用户迁移到 MySQL 8.4 LTS 或后续受支持版本。

这意味着,“数据库现在还能正常运行”已经不能作为继续停留在 8.0 的充分理由。

对于一个典型 Java 项目,更现实的问题已经变成:

MySQL 8.0 EOL 之后,到底应该升级到 8.4 LTS,还是一步到位迁移到新的 9.7 LTS?

答案并不是简单的“版本越高越好”。

对于绝大多数仍运行在 MySQL 8.0 上的存量 Java 系统,我更建议:

先把 8.4 LTS 作为第一阶段迁移目标,再根据项目生命周期决定是否继续升级 9.7 LTS。

原因不仅是稳定性,更重要的是 MySQL 官方升级路径本身就决定了 8.4 是一个非常关键的节点。

一、2026 年的 MySQL 版本体系已经变了

以前我们理解 MySQL 版本非常简单:

5.6 → 5.7 → 8.0。

几年出现一个主流大版本,大多数企业跟着升级即可。

现在 MySQL 已经正式采用两条发布路线:

发布路线 主要特点 更适合
LTS 长期支持、功能集合相对稳定 企业生产系统
Innovation 更快获得新特性和行为变化 新项目、技术验证、自动化测试成熟的团队

Oracle 官方说明,LTS 更适合需要稳定功能集合和较长支持周期的环境;Innovation Release 则更强调快速获得新功能和改进。

而到了 2026 年,还有一个容易产生误解的变化:

MySQL 9.7 本身已经是 LTS。

也就是说,现在不能再简单理解成:

“8.4 是稳定版,9.x 全都是创新版。”

更准确的关系是:

flowchart LR
    A["MySQL 8.0<br/>已 EOL"] --> B["MySQL 8.4 LTS"]
    B --> C["MySQL 9.0 ~ 9.6<br/>Innovation 演进"]
    C --> D["MySQL 9.7 LTS"]
    D --> E["后续采用<br/>YY.M 日历版本"]

MySQL 9.7 是旧数字版本体系下最后一个版本线。Oracle 已经开始转向日历版本命名,例如 MySQL 26.7 代表 2026 年 7 月版本。(MySQL 개발자区)

所以现在选择数据库版本时,应该关注的已经不是:

8.x 还是 9.x?

而是:

当前项目应该停在哪一个合适的 LTS 节点?

二、为什么 MySQL 8.0 项目仍然应该先关注 8.4

既然 9.7 已经是新的 LTS,一个很自然的问题就是:

那我现在还在 MySQL 8.0,为什么不直接上 9.7?

这里最重要的一点其实是 官方升级路径

MySQL 官方升级文档明确给出了:

MySQL 8.0 → MySQL 8.4 LTS

这一升级路线,并支持 In-place Upgrade、Logical Dump and Load 以及 Replication 等方式。

同时官方还明确说明:

Bugfix 或 LTS 系列不能被直接跳过。

因此对于目前仍停留在 MySQL 8.0 的系统而言,8.4 并不是一个没有意义的“过渡版本”,而是升级链路中的关键 LTS 节点。

从工程角度看,更合理的路线是:

flowchart LR
    A["MySQL 8.0"] --> B["升级兼容性检查"]
    B --> C["MySQL 8.4 LTS"]
    C --> D["稳定运行与观察"]
    D --> E{"是否需要继续升级?"}
    E -->|"暂时不需要"| F["继续维护 8.4 LTS"]
    E -->|"需要更长生命周期"| G["评估 MySQL 9.7 LTS"]

这样有一个很大的好处:

一次升级只处理一层主要变化。

如果直接把数据库、驱动、认证方式、SQL 行为以及整个应用运行环境同时进行大跨度调整,出现问题以后会很难判断到底是哪一层导致的。

三、那什么时候应该考虑直接以 9.7 LTS 为最终目标?

这里需要强调:

MySQL 9.7 LTS 并不是“不建议用于生产”。

恰恰相反,它本身就是新的长期支持版本。

真正的问题是你的项目处于什么阶段。

如果是一个已经稳定运行多年的存量系统,并且当前数据库还是 MySQL 8.0,那么先迁到 8.4 往往更加容易控制风险。

如果正在进行一次较大的基础设施重构,例如同时准备:

  • 升级 JDK;
  • 升级 Spring Boot;
  • 更换服务器;
  • 重建数据库集群;
  • 更换容器运行环境;
  • 调整数据库高可用方案;

那么就可以把 9.7 LTS 纳入最终目标版本进行整体评估。

可以简单理解为:

项目情况 更适合的策略
老系统,只想解决 8.0 EOL 优先 8.4 LTS
项目稳定,不需要新数据库能力 8.4 LTS
正在进行整体基础设施升级 评估 9.7 LTS
新系统,没有历史兼容包袱 可以直接评估最新 LTS
自动化测试不足、业务风险较高 优先减少升级跨度
有完整 DBA、灰度、回归体系 可以规划更积极的版本路线

数据库升级并不是版本号竞赛。

真正重要的是控制一次升级所引入的变量数量。

四、升级 MySQL 8.4,最容易踩坑的可能不是 SQL

很多开发者看到数据库升级,第一反应通常是:

我的 SQL 还能不能正常执行?

SQL 当然需要测试。

但从 MySQL 8.0 升级 8.4 时,一个非常值得优先检查的问题其实是:

数据库用户认证插件。

mysql_native_password 在 MySQL 8.0.34 就已经被标记为废弃;到了 MySQL 8.4,它默认被禁用;到了 MySQL 9.0,它已经被删除。

整个变化过程可以表示为:

flowchart LR
    A["MySQL 8.0.34<br/>开始废弃"] --> B["MySQL 8.4<br/>默认禁用"]
    B --> C["MySQL 9.0+<br/>正式移除"]

因此,数据库升级前非常值得执行一次:

SELECT
    user,
    host,
    plugin
FROM mysql.user;

如果发现某个应用用户仍然使用:

mysql_native_password

就应该提前处理,而不是等数据库升级以后 Spring Boot 启动失败才开始排查。

目前更加合理的认证方式通常是:

caching_sha2_password

例如:

ALTER USER 'app_user'@'%'
IDENTIFIED WITH caching_sha2_password
BY 'YourStrongPassword';

但生产环境不要直接修改。

更稳妥的做法是先创建测试用户或在测试环境修改,然后确认 Java 应用、Connector/J 和连接池全部能够正常工作。

五、Java 项目升级数据库,Connector/J 必须一起检查

一个 Java 项目连接 MySQL,中间其实经过了多层组件:

flowchart LR
    A["Spring Boot"] --> B["HikariCP / Druid"]
    B --> C["JDBC"]
    C --> D["MySQL Connector/J"]
    D --> E["MySQL Server"]

所以数据库升级以后出现连接异常,并不意味着问题一定出在数据库本身。

很多维护时间比较长的项目,可能已经升级过 Spring Boot、JDK、MyBatis,但 Connector/J 一直没有认真检查。

Maven 项目可以执行:

mvn dependency:tree

然后搜索:

mysql-connector-j

Gradle 项目则可以使用:

./gradlew dependencies

重点不是看 pom.xml 里有没有声明 MySQL Driver,而是看:

最终运行时真正加载的是哪个 Connector/J。

截至目前,MySQL 官方当前 Connector/J 版本支持 MySQL Server 8.0 及以上版本,并支持 JRE 8 及以上运行环境。

这并不意味着所有历史 Connector/J 都应该继续使用。

数据库升级正好也是一个检查 JDBC Driver 技术债的机会。

六、不要为了老项目长期重新打开 mysql_native_password

MySQL 8.4 默认关闭 mysql_native_password 后,一些历史项目可能无法正常连接。

这时候一种非常直接的处理方式是重新启用旧认证插件。

短时间作为应急迁移方案,它可能解决问题。

但如果把它作为长期方案,本质上只是把问题继续推迟。

因为官方已经明确给出了它的生命周期:

  • MySQL 8.0.34:废弃;
  • MySQL 8.4:默认关闭;
  • MySQL 9.0:删除。

所以真正合理的路线应该是:

flowchart LR
    A["发现旧认证账号"] --> B["检查 Connector/J"]
    B --> C["升级客户端依赖"]
    C --> D["切换新认证方式"]
    D --> E["Java 应用完整验证"]
    E --> F["淘汰旧认证"]

这样以后继续迁往新的 LTS 时,就不需要重新处理同一笔技术债。

七、另一个容易被忽略的问题:JDK 与 TLS

认证并不是唯一需要检查的连接问题。

对于比较新的 Java 项目来说,TLS 通常不会成为主要障碍。

真正需要注意的是一些历史系统,例如:

  • 较早版本的 JDK 8;
  • 很老的 Connector/J;
  • 多年没有升级的 Linux 环境;
  • 历史遗留下来的 SSL/TLS 参数。

这种项目平时可能一直正常运行,但数据库或者驱动升级以后,TLS 协商方式也可能暴露问题。

MySQL 官方当前 Connector/J 文档特别提到,较早的 Oracle Java 8 版本在 TLS 能力方面存在版本差异,例如 Java 8u261 之前的平台需要额外考虑 TLS 1.3 支持问题。

所以升级测试不要只验证:

SELECT 1;

能够执行。

真正需要验证的是完整 Java 应用。

八、升级前先让 MySQL 自己检查一次

MySQL Shell 提供了一个非常实用的工具:

util.checkForServerUpgrade()

它的作用就是在真正升级之前检查当前 MySQL 实例和目标版本之间可能存在的兼容问题。官方也明确建议在数据库升级前运行 Upgrade Checker。

例如:

util.checkForServerUpgrade(
    "root@127.0.0.1:3306",
    {
        targetVersion: "8.4.0"
    }
);

也可以通过命令行执行:

mysqlsh -- util checkForServerUpgrade root@127.0.0.1:3306 \
  --target-version=8.4.0

实际生产升级时,应把 targetVersion 修改为计划安装的具体目标版本。

Upgrade Checker 会执行自动检查,同时告诉你还有哪些内容需要人工进一步确认。

相比直接停止生产数据库然后安装新版本,这种方式显然更加可控。

九、数据库升级的测试单位应该是“应用”,而不是 MySQL

很多数据库升级测试实际上非常简单:

安装 MySQL 8.4,创建一个新数据库,启动 Spring Boot,首页能够打开。

然后得出结论:

升级没有问题。

这种测试是不够的。

因为真实生产数据库可能已经积累了很多特殊情况:

  • 历史表结构;
  • 大数据量表;
  • 老索引;
  • 特殊字符集和排序规则;
  • 存储过程;
  • Trigger;
  • Event;
  • 复杂动态 SQL;
  • 历史脏数据;
  • 特殊数据库账号。

这些东西在一个刚创建的空数据库里根本不存在。

更加可靠的测试路线应该是:

flowchart LR
    A["生产 MySQL 8.0"] --> B["备份 / 克隆"]
    B --> C["隔离测试环境"]
    C --> D["升级 MySQL 8.4"]
    D --> E["部署真实 Java 应用"]
    E --> F["完整业务回归"]
    F --> G["性能对比"]

MySQL 官方升级文档同样建议先在测试系统完成升级验证,确认工作正常以后再处理生产系统。


十、Java 应用至少要回归这些内容

数据库升级验证不要只测几个 Controller。

至少应该覆盖以下几类场景:

测试项 重点检查
数据库连接 启动、重连、连接池初始化
普通 CRUD 新增、查询、修改、删除
复杂查询 JOIN、GROUP BY、排序、分页
事务 提交、回滚、异常事务
MyBatis 动态 SQL、批处理
JSON JSON 字段读写和函数
大字段 TEXT、BLOB
定时任务 Spring Scheduling、XXL-JOB、Quartz
慢 SQL 执行计划是否变化
高并发 连接数、锁等待
批量任务 大批量插入和更新
报表 长 SQL、聚合查询

对于关键 SQL,可以重新执行:

EXPLAIN
SELECT ...;

如果希望看到真实执行信息,还可以根据场景使用:

EXPLAIN ANALYZE
SELECT ...;

重点关注升级前后是否出现明显的执行计划和性能变化。

十一、生产升级之前,必须先设计回滚

Java 应用发布失败以后,我们通常可以重新部署上一版 JAR。

数据库升级则没有这么简单。

数据库真正危险的地方在于:

升级完成后,业务可能已经继续产生新数据。

假设晚上 23:00 完成数据库升级,23:30 发现一个核心业务出现兼容问题。

这时候再问:

怎么退回 MySQL 8.0?

通常已经太晚了。

所以数据库升级必须同时存在两份方案:

Upgrade Plan 和 Rollback Plan。

至少需要提前回答:

  • 原数据库是否继续保留?
  • 升级过程中业务是否停止写入?
  • 新版本产生的数据如何处理?
  • 应用 JDBC 地址如何切回?
  • 旧数据库环境保留多久?
  • 数据备份是否真正做过恢复测试?
  • 出现什么级别的问题必须回滚?

MySQL 官方同样反复强调升级前备份数据,并建议首先在测试系统执行升级。

对于重要业务来说:

“我已经有备份”还不够。

真正有价值的是:

我已经验证这个备份能够恢复。

十二、核心业务更适合新环境迁移,而不是直接原地升级

对于个人博客、小型管理后台,停机维护以后直接升级数据库可能完全可以接受。

但如果是 ERP、订单、生产管理、SaaS 等核心系统,就可以考虑更加稳妥的迁移方式。

例如:

flowchart LR
    A["MySQL 8.0 生产库"] --> B["同步 / 复制数据"]
    B --> C["MySQL 8.4 新环境"]
    C --> D["Java 应用验证"]
    D --> E["控制生产写入"]
    E --> F["完成最终数据同步"]
    F --> G["切换 JDBC 连接"]
    G --> H["观察新环境"]

这种方案最大的优势不是升级更快。

而是:

原来的数据库还在。

如果新环境出现严重问题,回滚空间远大于直接修改唯一生产实例。

MySQL 官方支持通过 In-place、Logical Dump and Load、Replication 等方式完成 8.0 到下一 LTS 的升级,可以根据系统规模选择合适方案。

十三、我更推荐的 MySQL 8.0 升级流程

对于一个典型的 Spring Boot + MyBatis + MySQL 项目,可以按照下面的顺序推进:

flowchart LR
    A["确认当前 MySQL 8.0 版本"] --> B["检查数据库账号认证"]
    B --> C["检查 Connector/J"]
    C --> D["运行 Upgrade Checker"]
    D --> E["完整备份并验证恢复"]
    E --> F["克隆生产数据"]
    F --> G["测试环境升级 8.4"]
    G --> H["Java 应用完整回归"]
    H --> I["SQL 与性能对比"]
    I --> J["制定回滚方案"]
    J --> K["生产灰度 / 正式迁移"]
    K --> L["持续监控"]

真正升级 MySQL Server 软件本身,其实只是整个过程的一小部分。

真正决定升级是否可靠的是:

兼容性检查、应用回归、数据保护和回滚设计。

十四、到了 8.4 后,要不要继续升级 9.7?

这就回到了文章开始的问题。

如果已经稳定运行在 MySQL 8.4 LTS,而且:

  • 当前功能完全够用;
  • 没有生命周期压力;
  • 没有明确的新版本需求;
  • 系统属于高稳定性业务;

那么没有必要为了“版本更高”立即升级。

MySQL 官方对 LTS 的定位本身就是稳定功能集合和更长支持周期。

但如果你的系统还会长期维护很多年,正在规划下一轮基础设施升级,那么 9.7 LTS 就值得进入技术路线图。

这里真正应该采用的策略是:

flowchart LR
    A["MySQL 8.0 EOL"] --> B["先迁移 MySQL 8.4 LTS"]
    B --> C["稳定运行"]
    C --> D{"是否存在升级需求"}
    D -->|"没有"| E["继续维护 8.4"]
    D -->|"有"| F["评估 9.7 LTS"]

所以我的建议并不是:

MySQL 9.7 不好,不要升级。

而是:

不要因为 MySQL 8.0 EOL,就把一次必要升级变成一次不必要的大跨度改造。

十五、MySQL 8.0 EOL 真正提醒我们的是什么

很多 Java 团队非常重视应用代码升级。

JDK 会升级。

Spring Boot 会升级。

Redis 会升级。

前端框架会升级。

Docker 镜像也会升级。

但数据库经常成为那个“只要还能运行就不要碰”的组件。

结果几年以后,整个系统可能已经进入一种奇怪状态:

应用层非常新,基础设施部分组件却已经严重落后。

这种做法最大的问题不是今天不能运行。

而是技术债会不断积累。

最开始只是:

现在没必要升级。

几年以后就可能变成:

已经不敢升级了。

MySQL 8.0 在 2026 年正式 EOL,就是一个很明确的提醒:数据库、JDBC Driver、JDK、操作系统等基础组件同样存在生命周期,不能永久依靠“还能跑”判断是否需要维护。

十六、写在最后

对于目前仍然运行 MySQL 8.0 的 Java 项目,2026 年已经到了需要认真规划升级的时候。

但升级并不意味着盲目追最新。

更加合理的思路是:

flowchart LR
    A["MySQL 8.0"] --> B["处理历史技术债"]
    B --> C["检查认证与 JDBC"]
    C --> D["完成兼容性验证"]
    D --> E["建立备份与回滚能力"]
    E --> F["升级 MySQL 8.4 LTS"]
    F --> G["稳定运行"]
    G --> H["按实际需求评估 9.7 LTS"]

MySQL 8.4 和 MySQL 9.7 都是 LTS。

真正的区别不是哪个版本“更高级”,而是:

哪个版本更符合当前系统的迁移成本、生命周期和风险承受能力。

对于仍在 MySQL 8.0 的存量 Java 系统来说,我更倾向先把问题拆小:

先完成 8.0 → 8.4 的可靠迁移,处理认证插件、Connector/J、SQL、事务、备份和回滚等历史问题。

等系统重新站到一个受支持、稳定的 LTS 基线上,再决定下一步是否进入 9.7。

数据库升级最重要的从来不是:

“我用了最新版。”

而是:

在不破坏业务稳定性的前提下,让系统始终处于官方支持、安全、可维护,并且仍然能够继续演进的状态。

1 条评论
如果你觉得文章对你有帮助,那就请作者喝杯咖啡吧☕
微信
支付宝
  1 条评论
伴我   湖南省衡阳市

一天一篇技术长文,学不过来了chenqiangluolei