就地升级生产环境风险极高,必须先执行mysqlcheck --check-upgrade停写检查及util.checkForServerUpgrade深度扫描,修复所有ERROR级问题,并清理废弃参数、MyISAM系统表与残留配置后,方可启动8.0。

mysqlcheck --check-upgrade 必须在停写后执行
这是唯一能提前暴露表结构级不兼容的命令,不是可选项。它校验的是 5.7 表定义是否满足 8.0 元数据要求,比如:
- ENUM 字段默认值为空字符串(
DEFAULT '')→ 升级后报The table does not comply with the current version of MySQL - TEXT 或 BLOB 字段显式设了
DEFAULT ''→ 8.0 不允许 - 列名或存储过程名撞上
rank、json、group等 8.0 保留字 - 存在孤立
.frm文件或 MyISAM 分区表 → 启动卡死在 “Starting MySQL”
执行前务必停写(FLUSH TABLES WITH READ LOCK + 关闭应用写入),否则检查结果不可靠。命令格式:
mysqlcheck -u root -p --all-databases --check-upgrade
加 --fix-db-names 和 --fix-table-names 仅修正大小写,不解决语义问题,别依赖它们自动修复 ERROR。
util.checkForServerUpgrade() 报 ERROR 必须清零
这个检查比 mysqlcheck 深得多,专扫跨大版本语义变更,比如 NO_AUTO_CREATE_USER、utf8mb3 字符集、RocksDB 分区、系统库字段名变更等。它才是 Oracle 官方唯一推荐的前置动作。
关键实操点:
- 必须用目标版本的 MySQL Shell(如升到
8.0.42,就得用mysql-shell-8.0.42),混用 5.7 的 shell 会漏检 - 连接必须带 socket 路径:
./mysqlsh -uroot -p -S /tmp/mysql.sock -e "util.checkForServerUpgrade()" - 报告里
overallStatus不是 OK 就不能继续;任何ERROR级条目(非 WARNING)都必须逐条修复,例如:Usage of utf8mb3 charset→ 改库/表字符集;Column name 'rank' is a reserved keyword→ 重命名列 - 检查结果有效期仅 24 小时,超时得重跑
my.cnf 中残留废弃参数会导致 mysqld 直接退出
MySQL 8.0 启动时会对配置项做严格校验,遇到已移除参数会静默失败,日志只报 unknown variable,不指明哪一行。最常踩坑的有:
安装、修复、更新或打包一个基于 Python 和 PyMySQL 实现的 Windows `mysql` 命令。适用于用户希望在 PowerShell/CMD 中输入 `mysql` 时重定向到 Python 实现、需要交互式输入 MySQL 连接信息、需要同步到当前用户本地 bin 目录,或需要将该能力封装成可公开复用的 Codex skill。
-
query_cache_type、query_cache_size→ 8.0 已完全移除 -
expire_logs_days→ 替换为binlog_expire_logs_seconds -
explicit_defaults_for_timestamp→ 8.0 默认 true,且该参数已被弃用 -
innodb_file_format、log_warnings→ 启动报错退出
此外,这两项必须手动设好:
-
default_authentication_plugin=mysql_native_password→ 否则老 PHP/Java 客户端连不上,报错Client does not support authentication protocol -
sql_mode中删掉NO_AUTO_CREATE_USER→ 8.0 启动时校验失败,直接退出
替换二进制后启动失败,90% 是数据字典或权限表没清理干净
不是磁盘满了,也不是内存不够,而是 8.0 启动时自动执行数据字典升级,一旦发现底层不一致就拒载。典型表现是进程秒退、error log 里出现 Failed to initialize DD tables 或空日志。
排查重点:
- 确认
/var/lib/mysql下没有残留的 MyISAM 系统表:运行SELECT TABLE_SCHEMA, TABLE_NAME FROM INFORMATION_SCHEMA.TABLES WHERE ENGINE = 'MyISAM' AND TABLE_SCHEMA = 'mysql',结果非空就得先用skip-grant-tables启动 5.7,再执行ALTER TABLE mysql.plugin ENGINE=InnoDB - 检查 SELinux 上下文是否仍绑定旧路径:
ls -Z /usr/local/mysql,若显示 context 错误,需用semanage fcontext重置并restorecon - 确认
/etc/my.cnf.d/下无隐藏配置文件残留,rpm -qa | grep -i mysql(RHEL/CentOS)或dpkg -l | grep mysql(Ubuntu)确保无旧包残留 - 导入业务库前,确认目标 8.0 实例的
mysql库是全新初始化的——绝不能从 5.7 导出再导入mysql库,否则权限模型直接崩
真正危险的不是升级动作本身,而是你以为只是换了个二进制,其实 mysqld 启动那一刻就在后台重构整个数据字典和权限体系——这个过程不可中断、不可回退、不写 slow log,全靠 error log 排查,而 error log 里往往只有模糊提示。










