MySQL 5.5无法直接升级到8.0,因存在数据字典结构、认证插件和SQL模式三处不兼容断层,导致mysqld启动失败、系统表无法识别;必须经5.5→5.7→8.0分步迁移,且中间不可跳过5.7或替换为5.6。

直接跨大版本升级(5.5 → 8.0)不可行,必须分步迁移,否则 mysqld 启动失败、数据字典损坏、权限表无法识别是大概率事件。
为什么不能跳过 5.7 直接升到 8.0
MySQL 5.5 到 8.0 之间存在三处不兼容断层:数据字典从 MyISAM 表转为 InnoDB 系统表(5.7 引入)、密码认证插件变更(caching_sha2_password 默认启用)、SQL 模式默认收紧(ONLY_FULL_GROUP_BY 等强制生效)。8.0 的 mysqld 进程根本无法识别 5.5 的 mysql 系统库结构,启动时会报类似 Table 'mysql.user' doesn't exist 或 Incorrect definition of table mysql.db 的错误。
- 5.5 → 5.6 是平滑过渡(仅新增少量特性,系统表结构基本不变)
- 5.6 → 5.7 是关键跃迁(引入数据字典、JSON 类型、
ALTER TABLE ... ALGORITHM=INPLACE等) - 5.7 → 8.0 是架构重构(原子 DDL、角色管理、隐藏主键支持、重写优化器)
必须执行的三阶段升级路径
真实生产环境验证过的最小可行路径:5.5 → 5.7 → 8.0。中间不能省略 5.7,也不能用 5.6 替代。
- 第一阶段:5.5 → 5.7(使用
mysql_upgrade+ 手动清理)
先在新机器或新端口部署 MySQL 5.7,用mysqldump --all-databases --routines --triggers --events导出 5.5 全量数据;导入后运行mysql_upgrade -u root -p;重点检查mysql.help_topic和mysql.procs_priv是否被重建 - 第二阶段:5.7 → 8.0(必须用
--upgrade=FORCE)
停掉 5.7 服务,将datadir整体复制到 8.0 安装目录下;启动前确认my.cnf中已移除所有 5.7 不支持的参数(如query_cache_type);用mysqld --datadir=/path/to/data --upgrade=FORCE启动,而非普通启动 - 第三阶段:启动后必做三件事
执行SELECT @@version;确认是 8.0.x;运行mysqlcheck -u root -p --all-databases --check-upgrade验证表结构;手动执行ALTER USER 'root'@'localhost' IDENTIFIED WITH caching_sha2_password BY 'your_new_pass';(避免旧客户端连接失败)
最容易被忽略的三个配置陷阱
即便版本跳转成功,服务也跑起来了,以下三项不改,业务连不上、查询报错、字符乱码是常态。
-
lower_case_table_names=1必须显式设置
5.5 默认为 0(大小写敏感),8.0 在 Windows 上默认为 1,但 Linux 下仍为 0;若未在 5.7 阶段统一设为 1,升级后会出现“表存在却提示不存在”的诡异现象 -
sql_mode不能留空或沿用 5.5 默认值
8.0 默认启用STRICT_TRANS_TABLES,NO_ZERO_DATE,ERROR_FOR_DIVISION_BY_ZERO等;若业务 SQL 含隐式类型转换(如字符串拼接数字),会直接报错;建议在 5.7 阶段就设为STRICT_TRANS_TABLES,NO_ENGINE_SUBSTITUTION -
character_set_server=utf8mb4和collation_server=utf8mb4_0900_ai_ci要提前对齐
5.5 默认是latin1,8.0 默认是utf8mb4;如果只改服务器变量,没改已有表的列字符集,SHOW CREATE TABLE里仍显示latin1,后续插入 emoji 会截断
整个过程最耗时的不是执行命令,而是验证——每个阶段都要用业务 SQL 样本跑一遍,尤其注意含 GROUP BY、子查询、存储过程的语句,8.0 对窗口函数和 CTE 的解析逻辑与 5.5 完全不同,报错不会立刻出现,可能藏在某次聚合之后。


















