升级前必须做完整逻辑备份,用mysqldump --all-databases --single-transaction --routines --triggers --events导出全量数据;mysql_upgrade仅检查修复元数据,非真正升级;8.0默认字符集与排序规则变更影响查询结果;权限系统重构导致旧grant语句不可直接复用。

升级前必须做完整逻辑备份,mysqldump 不能只导出表结构
MySQL 版本升级不是「替换二进制文件」就完事,跳过备份直接升级等于给数据埋雷。很多团队用 mysqldump --no-data 验证兼容性,结果升级后发现存储过程里用了新版才支持的 JSON_TABLE,回退都来不及。
- 用
mysqldump --all-databases --single-transaction --routines --triggers --events导出全量逻辑备份,缺了--routines就丢存储过程,缺--events就丢事件调度器任务 - 别依赖
mysqlpump(5.7.8+)——它默认不导出DEFINER,升级后视图/函数可能因权限上下文失效 - 备份完立刻用
mysql -e "CHECK TABLE xxx"抽样校验几张大表,避免磁盘静默错误导致 dump 文件已损坏却没发现
mysql_upgrade 不是升级命令,只是兼容性检查和元数据修复工具
MySQL 5.7 升 8.0 后运行 mysql_upgrade,很多人以为它在“升级数据”,其实它只干三件事:检查系统表结构是否匹配当前版本、修复 mysql.user 表字段、更新 help_topic。真正的数据格式变更(比如 5.7 的 mysql.innodb_index_stats 表结构)由服务启动时自动完成。
- 8.0.16+ 版本已废弃
mysql_upgrade,启动 mysqld 时加--upgrade=FORCE才会强制执行元数据升级 - 如果跳过
mysql_upgrade(或等价操作),首次连接时遇到Table 'mysql.role_edges' doesn't exist这类报错,说明权限系统表未初始化,必须停库重跑 - 升级后首次启动若卡在
Upgrading MySQL tables,大概率是某张系统表被手动改过结构,需查 error log 里的具体表名,用mysqlcheck --repair mysql 表名单独修复
字符集与排序规则变更会导致查询结果突变
MySQL 8.0 默认字符集从 latin1 变成 utf8mb4,默认排序规则从 latin1_swedish_ci 变成 utf8mb4_0900_ai_ci。这不只是存储层面变化——ORDER BY、GROUP BY、索引范围扫描的结果都可能不同,尤其涉及中文、emoji 或大小写混合字符串时。
- 升级前用
SELECT @@collation_server, @@collation_database记下旧值,升级后对比;若要保持行为一致,启动 mysqld 时显式指定--collation-server=utf8mb4_unicode_ci -
utf8mb4_0900_ai_ci对标点符号更敏感,原来"abc." = "abc"返回 1,现在返回 0;应用层有字符串截断或模糊匹配逻辑的,必须重新测试 - 已有表不会自动改
COLLATE,得手动执行ALTER TABLE t CONVERT TO CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci,但注意:该操作会锁表,大表建议在低峰期用pt-online-schema-change
权限系统重构后,GRANT 语句导出结果不可直接复用
MySQL 8.0 彻底移除了 mysql.user 表里的 Password 字段,改用 authentication_string;同时角色(ROLE)成为一级对象,SHOW GRANTS 输出格式也变了。直接把旧库导出的 GRANT 语句在新库执行,大概率报错 ERROR 3719 (HY000): 'utf8' is deprecated and will be removed in a future release. 或 ERROR 1410 (42000): You are not allowed to create a user with GRANT。
- 用
mysqldump --no-create-info --no-data --skip-triggers --compact mysql user db event proc导出权限相关表原始数据,再用脚本清洗掉PASSWORD()函数调用和过时字段 - 新建用户必须用
CREATE USER 'u'@'h' IDENTIFIED WITH caching_sha2_password BY 'pwd',老版本的mysql_native_password插件虽仍可用,但客户端连接时可能因默认插件不匹配而失败 - 如果用了 Percona XtraBackup 做物理备份,恢复到 8.0 时必须确保备份时的 MySQL 版本 ≤ 目标版本,否则
xtrabackup --prepare会拒绝处理 5.7 备份生成的ibdata1
最麻烦的不是升级动作本身,而是那些没写进文档的隐式行为变更——比如 JSON 字段的 -> 操作符在 8.0.22 后对空数组返回 NULL 而非空字符串,这种细节只有在真实业务查询里才会暴露。











