不是必须,但跳过mysql_upgrade大概率导致查询报错或权限失效;它同步系统表结构变更,如user表字段调整、proc表编码更新,漏执行会导致密码错误、show grants为空、performance_schema为空等隐性故障。

升级前必须跑 mysql_upgrade 吗?
不是必须,但跳过它大概率导致后续查询报错或权限失效。高版本 MySQL(5.7→8.0 或 8.0.x→8.0.y)对系统表结构做了变更,mysql_upgrade 的本质是执行一系列 ALTER TABLE 和 UPDATE 来同步 mysql 库里的元数据——比如 user 表字段变长、新增 password_last_changed,或者 proc 表编码调整。
常见错误现象:ERROR 1820 (HY000): You must reset your password using ALTER USER statement(其实是旧密码哈希格式不被识别),或 SHOW GRANTS 返回空、存储过程调用失败。
- MySQL 8.0.16+ 默认禁用
mysql_upgrade,改由服务启动时自动执行;但前提是mysqld启动参数里没加--skip-grant-tables,且磁盘空间足够 - 手动运行时,必须用 root 连接本地 socket(不能走 TCP),且确保
mysqld已停止,否则会锁表失败 - 如果升级后发现
performance_schema表全为空,八成是漏了这步——它不报错,但静默跳过
备份策略里最容易被忽略的 mysql.ibd 和 ibdata1
逻辑备份(mysqldump)救不了你——它不包含 InnoDB 共享表空间的真实状态。升级失败回滚时,若只保留 .sql 文件,重建库后可能因 ibdata1 里事务 ID、回滚段偏移等元信息不一致,直接触发崩溃。
真实场景:从 5.6 升 5.7,即使 mysqldump 导出再导入,也可能出现 InnoDB: Error: page 3 log sequence number ... is in the future!。
- 物理备份必须包含整个
datadir下所有文件:不只是*.ibd,还有ibdata1、ib_logfile*、mysql/目录,以及auto.cnf(含 server-uuid,重复会导致主从异常) -
my.cnf里的innodb_file_per_table=ON不代表可以只备份*.ibd;ibdata1仍存全局数据字典和 undo logs,缺失即不可恢复 - 用
Percona XtraBackup时注意版本匹配:XtraBackup 2.4 只支持到 MySQL 5.7,8.0 必须用 8.0.x 版本,否则备份出来的backup-my.cnf会漏掉innodb_redo_log_capacity等新参数
sql_mode 变更引发的隐式失败
MySQL 5.7 默认开启严格模式(STRICT_TRANS_TABLES,NO_ENGINE_SUBSTITUTION),8.0 更进一步加入 STRICT_ALL_TABLES 和 NO_ZERO_DATE。很多老业务写的 INSERT INTO t VALUES (NULL, '') 在低版本能插,在高版本直接报错,而且错误可能藏在应用日志深处,不触发事务回滚。
典型表现:升级后部分报表导出卡住、定时任务失败但无明确报错、SELECT COUNT(*) 结果突降——其实是插入失败后数据没进来,但应用没检查 mysql_affected_rows()。
- 升级前先在测试库执行
SELECT @@sql_mode;,对比新旧值;重点盯ONLY_FULL_GROUP_BY(会让SELECT a,b FROM t GROUP BY a报错)和NO_AUTO_CREATE_USER(影响GRANT语句语法) - 不要全局关 strict mode;建议在应用连接串里加
sql_mode=覆盖,或对单条语句用SET SESSION sql_mode='...';临时兼容 - 8.0.11+ 移除了
CREATE TEMPORARY TABLES权限的隐式授予,如果旧代码依赖未显式授权的临时表操作,会直接ERROR 1142
字符集与排序规则迁移陷阱
MySQL 8.0 默认字符集从 utf8mb4 升级为 utf8mb4_0900_as_cs,排序规则变了。不是所有 utf8mb4 字段都能无感继承——尤其当字段定义里硬写了旧排序规则(如 utf8mb4_unicode_ci),升级后 ALTER TABLE ... CONVERT TO CHARACTER SET utf8mb4 会失败,提示 Collation 'utf8mb4_unicode_ci' is not valid for character set 'utf8mb4'。
更隐蔽的问题:utf8mb4_0900_as_cs 区分大小写和重音,原来 WHERE name='Li' = 'LI' 为 true,现在可能为 false,导致索引失效或去重逻辑错乱。
- 升级前用
SELECT TABLE_SCHEMA,TABLE_NAME,COLUMN_NAME,COLLATION_NAME FROM information_schema.COLUMNS WHERE COLLATION_NAME LIKE 'utf8mb4%';扫描所有列,标记非默认排序规则的字段 -
mysqldump导出时加--set-gtid-purged=OFF --column-statistics=0,避免 8.0 新增的直方图统计干扰导入 - 如果必须保留旧排序规则,可在 my.cnf 里显式设
collation-server=utf8mb4_unicode_ci,但要注意:这会影响新建库/表的默认行为,且无法覆盖已存在的字段定义
真正麻烦的不是升级动作本身,而是那些没报错却悄悄改变语义的地方——比如一个 GROUP BY 查询结果顺序变了,没人盯着看,上线两周才被业务方发现。











