多实例MySQL升级前必须确认的3个状态:mysqld--version输出是否统一、每个实例的datadir是否可写、配置文件中是否含已废弃参数。

多实例 MySQL 升级前必须确认的 3 个状态
不检查就跑脚本,90% 的批量升级会卡在某个实例上静默失败。重点不是“怎么升”,而是“能不能升”。
-
mysqld --version输出是否统一?混用 5.7 和 8.0 实例时,mysql_upgrade命令行为完全不同,不能一概而论 - 每个实例的
datadir是否可写?常见坑:SELinux 启用时,新二进制文件无法访问旧数据目录,报错Can't open the mysql.plugin table - 配置文件中是否含已废弃参数?比如 8.0 升级后仍保留
query_cache_type,会导致mysqld启动失败且无明确提示
用 shell 脚本控制多个 mysqld 实例启停与升级流程
别依赖 systemctl —— 多实例通常用自定义 service 文件或直接调用 mysqld,systemd 单元名不统一反而增加判断负担。
- 用
pidfile而非端口判断进程存活:kill -0 $(cat /var/lib/mysql-3307/mysqld.pid) 2>/dev/null比netstat -tln | grep :3307更可靠 -
mysql_upgrade必须指定--socket和--user,否则默认连 localhost:3306,升级错实例 - 升级命令建议加
--force,但仅限 5.7→8.0 这类大版本;小版本(如 8.0.32→8.0.33)禁用,避免掩盖权限问题
for d in /var/lib/mysql-*; do
port=$(basename $d | sed 's/mysql-//')
sock="$d/mysql.sock"
if [ -S "$sock" ]; then
mysql_upgrade --socket="$sock" --user=root --password='xxx' --force
fi
done
升级后验证不能只看“启动成功”
很多脚本停在 service mysqld-3307 start 返回 0 就认为 OK,实际 information_schema 表结构可能损坏、复制通道中断、甚至 performance_schema 初始化失败。
- 对每个实例执行
mysql --socket=/path/to.sock -e "SELECT VERSION(), @@hostname;",确认版本号和实例标识匹配 - 检查
SHOW SLAVE STATUS\G(如有),Seconds_Behind_Master非 NULL 才算复制链路可用;升级后常因 GTID mode 变更导致 IO_THREAD 停止 - 运行
mysqlcheck --all-databases --check-upgrade --socket=...,它比mysql_upgrade更早暴露兼容性问题,比如分区表引擎不一致
路径和权限问题最容易被忽略
升级包解压到 /usr/local/mysql-8.0.33 后,所有实例的 basedir 都要指向它,但 datadir 和 pidfile 必须保持原路径不变——改错一个,整个实例就不可逆损坏。
- 软链接
/usr/local/mysql指向新版目录没问题,但务必用readlink -f校验,避免嵌套软链导致mysqld解析出错 - 新版二进制默认要求
mysql用户拥有basedir下所有文件所有权,而老实例常是root启动、mysql运行,chown -R mysql:mysql /usr/local/mysql-8.0.33是必须步骤 -
my.cnf中若用相对路径写log-error = ./mysqld.err,升级后日志可能写到/usr/local/mysql/下,而非你预期的/var/log/mysql/
升级不是替换二进制那么简单,每个实例的启动上下文都得单独过一遍 —— 特别是那些没进 CMDB、靠运维记忆维护的老实例。










