生产环境MySQL大版本升级必须采用迁移升级而非就地升级,即通过新实例部署、数据迁移与流量切换实现,确保旧库持续可用,规避就地升级导致的系统表损坏与元数据不一致风险。

生产环境升级必须走迁移升级,不是就地升级
MySQL大版本升级(如5.7→8.0、8.0→8.4)在生产环境里,in-place upgrade 是高风险操作,官方明确不推荐用于核心业务。真正稳妥的路径是迁移升级(Migrating Upgrade),本质是“新实例+数据迁移+流量切换”,全程旧库不中断。
- 就地升级失败可能导致
innodb_system表空间损坏、mysql系统库元数据不一致,恢复困难 - 迁移升级失败可秒级切回原库,RTO可控;就地升级失败往往需要从备份恢复,RTO动辄数小时
- MySQL 8.4已移除
mysql_upgrade工具,所有升级动作由mysqld --upgrade=FORCE自动触发——但该机制只保障单机一致性,不解决SQL兼容性、认证插件、字符集等跨版本语义差异
升级前必须跑通三件事:备份验证、兼容性检查、测试环境全链路压测
很多团队卡在“备份做了但没验证”或“测试只连得上,没跑真实SQL”。这三件事缺一不可:
-
mysqldump导出后,必须用mysql --force导入新实例并执行SELECT COUNT(*)比对关键表行数;物理备份(XtraBackup)还原后,必须运行innochecksum校验ibd文件完整性 - 在旧版本上运行
util.checkForServerUpgrade()(MySQL Shell内置),它会报出ERROR 1286 (42000): Unknown storage engine 'TEMPORARY'这类8.0.30+强制要求显式指定引擎的问题,以及caching_sha2_password插件导致老客户端连接失败的风险点 - 测试环境必须用真实应用流量回放(例如
pt-query-digest --replay),不能只跑SELECT;特别关注GROUP BY行为变化、JSON_CONTAINS函数返回类型、生成列(generated column)索引是否生效
配置项和SQL模式变更必须提前清理,不能等启动时报错再改
MySQL 8.0+默认启用STRICT_TRANS_TABLES,且移除了query_cache_type等参数。这些不是“警告”,而是直接导致mysqld启动失败或查询报错。
- 删掉
my.cnf里的old_passwords=1、explicit_defaults_for_timestamp=OFF(8.0.2起强制ON)、sql_mode=NO_AUTO_CREATE_USER(已废弃) - 把
default_authentication_plugin=mysql_native_password加进配置——否则应用用5.7客户端连8.0+会报Authentication plugin 'caching_sha2_password' cannot be loaded - 检查所有
CREATE TEMPORARY TABLE ... SELECT语句,补上ENGINE=InnoDB;搜索CREATE TABLE ... AS SELECT,确认目标表引擎是否被隐式推断为MyISAM(8.0已移除)
升级窗口内最关键的三个动作:停写控制、binlog位点记录、切换后立即验证主键冲突
迁移升级不是“一键切换”,而是精细的流量控制过程。最容易被忽略的是主键冲突验证——尤其当业务使用AUTO_INCREMENT且未设auto_increment_offset/auto_increment_increment时,双写期间可能产生重复ID。
- 停写不等于停服务:用
SET GLOBAL super_read_only = ON+FLUSH TABLES WITH READ LOCK冻结写入,同时保持读流量;记录SHOW MASTER STATUS输出的File和Position作为最终同步位点 - 新实例导入完成后,必须执行
SELECT * FROM INFORMATION_SCHEMA.INNODB_TABLESPACES WHERE NAME LIKE 'mysql/%'确认数据字典加载完整;运行mysqlcheck -u root -p --all-databases --check快速扫描表结构异常 - 流量切换后第一件事:查
SELECT MAX(id) FROM order_table和SELECT MAX(id) FROM order_table_old(旧库别名),确认无ID跳跃或重叠;抽样查几条带JSON字段的记录,验证->操作符解析是否一致
真正的难点不在命令执行,而在每个环节的“确认信号”是否拿到——比如mysqld进程起来不代表服务可用,SELECT 1成功不代表事务能提交,INSERT成功不代表二级索引没丢数据。生产升级没有“差不多”,只有“确认了”和“没确认”。


















