停服务前必须做三件事:备份(逻辑+权限+物理)、检查(兼容性扫描)、清理(断连+安全关库);升级需替换二进制、配置default_authentication_plugin和字符集、用mysqld_safe启动触发自动升级;升级后必验版本、认证插件、引擎、group by行为及错误日志。

停服务前必须做三件事:备份、检查、清理
直接升级 MySQL 5.7 → 8.0 不是“替换二进制再启动”就完事了——90% 的失败都卡在升级前没做对这三步。
-
备份要分层:用
mysqldump -u root -p --all-databases --routines --triggers --events备业务库;用mysql -e "SELECT CONCAT('SHOW GRANTS FOR ''',user,'''@''',host,''';') FROM mysql.user" | mysql | sed 's/$/;/g'单独导出权限;再用cp -rp /var/lib/mysql /var/lib/mysql.bak.57做物理快照(别只信逻辑备份) -
检查不能跳过:MySQL 8.0 不支持 MyISAM 系统表、
NO_AUTO_CREATE_USER模式、查询缓存等。先在 5.7 上跑mysqlcheck --check-upgrade,再用mysqlsh -uroot -p -S /tmp/mysql.sock -e "util.checkForServerUpgrade()"做兼容性扫描——它会明确告诉你哪张表引擎不合法、哪个用户密码策略过期、哪些 SQL 模式已废弃 -
清理连接和状态:执行
show processlist;确认无活跃连接;设SET GLOBAL innodb_fast_shutdown = 0;避免脏页残留;再shutdown;关库——别用kill -9,否则 8.0 启动时可能报InnoDB: Database page corruption
in-place 升级实操:替换、启动、自动升级系统表
CentOS/Ubuntu 下 in-place 升级本质是「换 bin 目录 + 换配置 + 启动触发自升级」,不是重装。
- 停库后,把新版本
mysql-8.0.31-linux-glibc2.12-x86_64解压到新路径(如/opt/mysql8),用软链指向它:ln -sf /opt/mysql8 /usr/local/mysql - 复用原
my.cnf,但必须显式加两行:default_authentication_plugin=mysql_native_password(避免应用连不上)、character-set-server=utf8mb4(防止 utf8mb4 表被降级成 latin1) - 启动命令要用
mysqld_safe --defaults-file=/etc/my.cnf --user=mysql &——注意不是systemctl start mysqld,否则 systemd 可能调用旧 service 文件;首次启动时,8.0.16+ 会自动执行系统表升级(mysql_upgrade已弃用),日志里出现Upgrading system tables.即表示成功
升级后必验的五个致命点
服务起来≠升级完成。MySQL 8.0 默认行为变化极多,不验证等于埋雷。
-
SELECT @@version, @@sql_mode;看是否真为 8.0.x,且sql_mode里没有NO_AUTO_CREATE_USER(否则建用户报错) -
SELECT user, host, plugin FROM mysql.user;检查 root 是否还是mysql_native_password,不是的话用ALTER USER 'root'@'localhost' IDENTIFIED WITH mysql_native_password BY 'xxx';改回来 -
SHOW ENGINES;确认InnoDB是默认引擎,且MyISAM状态为NO(8.0 系统表全 InnoDB,老 MyISAM 表需手动ALTER TABLE t ENGINE=InnoDB;) - 用原应用连接测试,重点看带
GROUP BY的语句是否报Expression #1 of SELECT list is not in GROUP BY clause——这是 8.0 严格模式默认启用,需调整sql_mode或重写 SQL - 查
error log最后 200 行,确认无Failed to upgrade server、Table upgrade failed类错误;有则立即停库,回退到备份
为什么建议跳过 5.7.x → 8.0.y 直升,先打补丁?
不是所有 5.7 都能平滑升 8.0。官方只保证从「5.7 最新 GA 版」(如 5.7.40)开始升级路径受支持。
- 若你还在用 5.7.23、5.7.30 这类老版本,先升级到
5.7.40(只需 rpm -Uvh 或 tar 替换),再升 8.0——可避开大量已知 bug,比如 5.7.32 之前存在innodb_undo_log_truncate兼容问题,升 8.0 时直接卡死 - 8.0.16 是关键分水岭:此前必须手动跑
mysql_upgrade;此后由mysqld自动完成。但自动升级只处理系统库,你的业务库字符集、索引、JSON 字段仍需人工核对 - 最易被忽略的是时区表:5.7 的
mysql.time_zone*表结构与 8.0 不兼容,升级后若发现CONVERT_TZ()返回 NULL,就得手动运行mysql_tzinfo_to_sql /usr/share/zoneinfo | mysql -u root -p mysql










