mysql小版本原地升级可行是因为同主版本内数据格式与系统表结构兼容,只需替换二进制文件并执行mysqld --upgrade=force重启;须确保不跳版本、不混发行版,并完成空间、引擎、sql模式三项检查。

MySQL 小版本升级为什么能原地做
因为同一大版本下的小版本(比如 8.0.33 → 8.0.34)是向后兼容的:数据文件格式没变、系统表结构没变、mysqld 启动时能直接识别旧数据目录。这不是“迁移”,而是“替换二进制文件 + 重启服务”。但前提是——你没跳过中间小版本,也没混用不同发行版(比如从 Oracle 官方包切到 Percona Server)。
常见错误现象:mysqld 启动失败,报错 Table 'mysql.func' doesn't exist 或 Unknown table engine 'InnoDB',基本都是跳版本或未运行 mysql_upgrade(新版已弃用,实际应执行 mysqld --upgrade=FORCE)。
- 只适用于同一主版本内升级(
5.7.x → 5.7.y,8.0.x → 8.0.y),跨主版本必须停机迁移 - 确认当前
mysql --version和目标包的mysqld --version输出是否都落在8.0.*这类一致主版本下 - 官方 tar.gz 包和系统包管理器(apt/yum)升级行为不同:后者可能自动执行
--upgrade,前者必须手动触发
原地升级前必须做的三件事
不是“备份完就能上”,而是备份只是底线。真正决定成败的是这三项检查:
- 检查
datadir所在文件系统剩余空间 ≥ 当前ibdata1 + ib_logfile*总和的 2 倍(升级过程会写临时日志、重建部分系统表) - 确认所有表引擎为
InnoDB或CSV/MEMORY;MyISAM表在 8.0.34+ 已被禁用,升级会失败 - 执行
SELECT VERSION(), @@sql_mode;,若返回STRICT_TRANS_TABLES以外的严格模式(如含NO_AUTO_CREATE_USER),需提前清理——该模式在 8.0.11+ 已移除,升级时会报错
升级命令执行顺序不能错
顺序错了轻则启动卡住,重则元数据损坏。核心原则:停服务 → 换二进制 → 修权限 → 强制升级 → 启服务。中间任何一步跳过或颠倒,都会让 mysqld 拒绝启动。
- 停服务:
systemctl stop mysql(或service mysqld stop),确认ps aux | grep mysqld无残留进程 - 替换二进制:
cp /path/to/new/mysqld /usr/sbin/mysqld,注意保留原mysqld_safe(如使用)和配置文件位置不变 - 修复权限:
chown -R mysql:mysql /usr/sbin/mysqld,尤其当新包解压自 root 用户时,否则启动报Permission denied - 强制升级:
mysqld --datadir=/var/lib/mysql --upgrade=FORCE(路径按实际改),不加--upgrade参数会导致后续启动失败
升级后第一件事不是连业务,而是验证元数据
很多团队升级后立刻切流量,结果半小时后发现 performance_schema 表缺失或 information_schema 字段类型异常。这是因为 --upgrade=FORCE 只保证系统表结构就绪,不校验业务表一致性。
- 先连本地:
mysql -u root -S /var/run/mysqld/mysqld.sock,避免走网络层干扰判断 - 快速验证:
SELECT COUNT(*) FROM mysql.user;(非空)、SHOW ENGINES;(InnoDB 行 State = YES)、SELECT * FROM performance_schema.setup_actors LIMIT 1;(不报错) - 如果业务用到
mysql_innodb_cluster_metadata库(Group Replication / InnoDB Cluster),必须运行mysqlsh --sql -e "ALTER INSTANCE RESTART"触发元数据刷新
最易被忽略的是 slow log 格式变更:8.0.30+ 默认启用 log_output='TABLE',但旧配置若设了 slow_query_log_file,升级后会静默失效。得手动删掉该配置项再重启。










