不建议生产环境使用in-place升级,应采用mysqldump逻辑迁移:导出时加--single-transaction保障innodb一致性,myisam需--lock-all-tables或停写;导入8.0前需临时禁用严格sql_mode防日期错误,并校验外键、自增id、字符集及认证插件兼容性。

in-place 升级在生产环境极不安全,**不建议直接执行**。真正能落地的方案是逻辑升级:用 mysqldump 导出 + 在全新 MySQL 8.0 实例中导入,把兼容性问题暴露在测试阶段,而不是凌晨三点的生产库上。
为什么 mysqld --upgrade=FORCE 不等于“跳过校验”
mysqld --upgrade=FORCE 只补全缺失的系统表,不会绕过元数据一致性检查。已存在的表结构冲突(如 mysql.roles 与用户自定义同名表)仍会启动失败。
- 真正跳过自动升级需配合
--upgrade=NONE,但前提是已手动重建干净的mysql系统库(例如通过mysqldump --all-databases导出再导入) - 若误用
--upgrade=FORCE启动只读实例或权限受限环境,会直接报错Table 'mysql.component' doesn't exist,日志里没有更多上下文 - MySQL 8.0 启动时强制校验字符集、
sql_mode、系统表结构 —— 很多 5.7 “能跑”的状态,在 8.0 下直接被拒绝
mysqlcheck --check-upgrade 是红绿灯,不是提示器
这个命令必须在干净环境中运行,否则报错即停,不能硬扛。
- 发现孤立
.frm文件(比如手动删了.ibd没DROP TABLE)→ 必须先修复或删除对应表,否则中断 - 查出 MyISAM 分区表:
SELECT TABLE_SCHEMA, TABLE_NAME FROM INFORMATION_SCHEMA.TABLES WHERE ENGINE = 'MyISAM' AND CREATE_OPTIONS LIKE '%partitioned%'→ 全部ALTER TABLE ... ENGINE=InnoDB -
mysql库下有自定义表名与 8.0 新系统表重名(如roles、role_edges、columns)→ 必须重命名或删掉,否则初始化失败
配置文件残留废弃参数会导致 mysqld 启动失败
哪怕只留一个已移除参数,mysqld 就起不来,错误日志里只有模糊的 unknown variable 提示。
- 必须删掉:
query_cache_type、explicit_defaults_for_timestamp、log_warnings - 软链接切换更安全:解压新包到独立路径(如
/usr/local/mysql-8.0.42),再用ln -sf指向它,避免硬编码路径污染 - 宝塔面板用户注意:7.9+ 的「软件商店 → MySQL → 升级」按钮调用的是官方
mysql_upgrade,但它仍依赖底层 in-place 路径,风险未消除;仍建议走逻辑升级
逻辑升级后必须立即验证的三件事
导入完成 ≠ 升级成功。很多问题在应用连上来之后才暴露。
- 检查默认校对规则:
SELECT DEFAULT_COLLATION_NAME FROM INFORMATION_SCHEMA.SCHEMATA WHERE SCHEMA_NAME = 'your_db'→ 应为utf8mb4_0900_ai_ci - 确认认证插件:
SELECT user, host, plugin FROM mysql.user→ 若旧应用连接报Client does not support authentication protocol,需立刻执行ALTER USER 'xxx'@'%' IDENTIFIED WITH mysql_native_password BY 'pwd' - 验证
sql_mode是否含已移除项:SHOW VARIABLES LIKE 'sql_mode'→ 若含NO_AUTO_CREATE_USER,启动会失败,必须从备份 SQL 或配置中清除
mysql.events 表,或者 ORM 自动生成的 DDL 里写了 TIMESTAMP 却没显式设 DEFAULT。这些点在逻辑升级的导出/导入过程中就会提前炸出来,而不是等流量切过去才崩。











