尧图网站设计 尧图网站设计YAOTU DESIGN
ARTICLE DETAIL

资讯详情

深耕网站设计与一线实操的经验洞察。

MySQL 升到 8.4 前的兼容性自检清单

MySQL 升到 8.4 前的兼容性自检清单 MySQL 8.0 在 2026 年 4 月 30 日 的支持停了最后一个可用版本号是 8.0.46。8.0 是 2018 年 4 月 19 日 GA 的一路服役了八年。很多生产库现在还跑着它。大部分人第一次听说要升级是在一份安全扫描报告里。升级教程到处都是讲怎么升的居多。少有人讲升之前该查什么。真正麻烦的地方在于8.4 有一批变更不给兼容期。有些在 8.0 里只是个 Warning到 8.4 变 Error。有些建表语句在 8.0 里能过在 8.4 里直接被拒。而且这些不会在启动时提醒你只有执行到那一条才暴露。先说这次的机器。云服务器4 核 8G跟 Web 服务共用一台。数据库是 MySQL 8.4.11容器镜像 mysql:8.4.11。1Panel 容器化部署端口只映射到 127.0.0.1:3306不暴露公网。要升的是 8.0.x 社区版。应用侧是 PHP 8.4 加 ThinkPHP 8走 PDO 连接。命令里用变量代替容器名先在终端跑一次# 换成你在 1Panel 里给 MySQL 起的名字 容器名exportMYSQL_CTNmysql84标「实测」的结果来自我这次部署2026 年 9 月 16 日和 17 日原始回显原样保留。标「官方」的来自 MySQL 官方文档和发布说明出处随文给出。8.0 的 GA 是 2018 年 4 月 19 日支持终止 2026 年 4 月 30 日已经 EOL。8.4 LTS 的 GA 是 2024 年 4 月 30 日支持到 2032 年 4 月 30 日还在支持期内。9.7 LTS 更新一些GA 是 2026 年 4 月 21 日支持到 2034 年 4 月 21 日。EOL 意味着三件事同时停。不再有安全补丁。不再有 bugfix 版本8.0.46 是最后一个构建。不再有支持案例。MySQL 官方 8.0 发布说明页的第一段就写着这段原文As of April 2026, with version 8.0.46,MySQL 8.0 reaches End of Life (EoL).MySQL 8.0 users are encouraged to upgrade to the latestMySQL 8.4 LTS or MySQL Innovation release.为什么不直接上 9.7因为它 2026 年 4 月才 GA驱动、ORM、运维工具、云厂商托管这些生态都还在跟进。8.4 是从 8.0 出发的原地升级路径官方明确支持风险面最小。所以 8.0 到 8.4 是眼下最稳的一步。但这一步得先过下面这道关。8.4 有五条变更值得单独盯。第一条非标准外键。MySQL 官方 8.4 发布说明原文The use of non-unique or partial keys as foreignkeys is deprecated in MySQL. Beginning with thisrelease, you must explicitly enable such nonstandardkeys …restrict_fk_on_non_standard_key… is ON bydefault. This means that any attempt to use anonstandard key as a foreign key in aCREATE TABLEorALTER TABLEstatement is rejected with the errorER_FK_NO_INDEX_PARENT.翻译过来就是外键引用的父表列必须有唯一键或者主键。8.0 时代父表上随便一个普通索引也能建外键8.4 默认不许了。这里有个容易误读的地方官方文档专门澄清过。我一开始以为升级那一刻就会炸其实升级本身不受影响。8.0 库里已经存在的非标准外键可以带过来服务器在升级时会打一串警告把它们的名字列出来。被拒的是新建这种外键。所以风险不在升级那一刻在升级之后。某天你加一张新表顺手写了个老习惯的外键建表直接失败。第二条FLOAT 和 DOUBLE 上的 AUTO_INCREMENT。Percona 的 8.0 与 8.4 默认值对照里写得很直白。8.0 是 deprecated with warnings能用但报废弃警告。8.4 是 completely removed直接报错。一条 SQL 就能扫完SELECTtable_schema,table_name,column_name,data_typeFROMinformation_schema.columnsWHEREextraLIKE%auto_increment%ANDdata_typeIN(float,double);空结果才说明安全。有结果的话升级前把那些列改成整数类型比如 BIGINT。第三条新增保留字。8.4 加了一批保留字MANUAL、PARALLEL、QUALIFY、TABLESAMPLE 都在里面。你要是把其中任何一个当成没加引号的表名或列名查询直接语法错误。这条最阴的地方在于升级当下它不报。等升级之后某条 SQL 突然跑不通报的还是语法错误看着像代码被人改坏了。自检就是把这几个词在表名和列名里搜一遍SELECTtable_name,column_nameFROMinformation_schema.columnsWHEREcolumn_nameIN(manual,parallel,qualify,tablesample);有命中就把标识符用反引号包起来或者改名。第四条int(11) 这类显示宽度写法。int(11)、bigint(20) 里括号里的数字是显示宽度跟存储范围没关系。这个写法从 8.0.17 起就被标记成废弃。它不会导致升级失败目前还只是警告。但既然要动一次数据库顺手把新表的写法改掉是划算的。新建表直接写 int 或 bigint不写宽度。判断依据也简单。这类写法只出现在你手写的 DDL 里。ORM 生成的迁移脚本、新版本工具导出的结构默认都不带。第五条认证插件。8.4 沿用了 8.0 的默认插件 caching_sha2_password。但它更进一步把 mysql_native_password 默认禁掉了。这个插件在 8.0.34 就标了废弃9.0 会彻底移除。直接后果是老客户端连不上。比如 Navicat 11 及更早版本会报Authentication plugin caching_sha2_password cannot be loaded正确的做法是升级客户端Navicat 16 或者 DBeaver而不是把认证插件改回去。改回去只是把问题推到 9.0。应用侧不用慌。PHP 的 PDO 和 mysqli 从 7.4.4 起就支持 caching_sha2_password。只要你的 PHP 不低于 7.4.4代码不用动。这五条里FLOAT 和 DOUBLE 那条、保留字那条是纯 SQL。外键和显示宽度要扫 DDL 文本认证插件查客户端版本。扫 DDL 文本用正则就够不用上工具。关键是扫的对象要全不只是建表脚本还要包括所有 ALTER TABLE 和迁移文件# ① 外键找出所有 FOREIGN KEY 定义人工过一眼有没有引用非唯一键grep-rniEforeign key--include*.sql.# ② 显示宽度int(11) / bigint(20) 这类写法grep-rnE\b(int|bigint|tinyint|smallint|mediumint)\([0-9]\)--include*.sql.# ③ 新增保留字当标识符用反引号包住的不算问题grep-rniE(^|[^a-z_])(manual|parallel|qualify|tablesample)([^a-z_]|$)--include*.sql.三条命令的判据统一。空结果就是没有要处理的地方。有结果不等于有问题但每一条都值得看一眼。我这套要升的库把五条全扫了一遍。这张清单我当时是照着一条条跑的。非标准外键 0 处全库外键数量本来就是 0。FLOAT 和 DOUBLE 加 AUTO_INCREMENT 0 处。8.4 新增保留字冲突 0 处。int(11) 显示宽度写法 0 处。排序规则声明 31 处全部是 utf8mb4_unicode_ci8.4 完整支持。PDO 驱动版本是 PHP 8.4.25远高于 7.4.4支持 caching_sha2_password。结论是脚本零改造直接上 8.4。这里最值得说一句的是外键数量为 0。这不是运气。它同时说明两件事。一是不受非标准外键那条新规则影响。二是这个库从一开始就没打算靠数据库层保证引用完整性这本身是个取舍不是这篇的主题。另外那 31 处 utf8mb4_unicode_ci 有个隐藏前提。8.4 的 utf8mb4 默认排序规则是 utf8mb4_0900_ai_ci。我的脚本里写的是 utf8mb4_unicode_ci。建库时如果留空排序规则库级会拿到那个新默认值。它跟表级的 utf8mb4_unicode_ci 混在一起跨表 JOIN 做字符串比较就会报Illegal mix of collations (utf8mb4_0900_ai_ci,IMPLICIT) and (utf8mb4_unicode_ci,IMPLICIT) for operation 所以建库那一项必须显式选不能靠默认值。
返回列表