MySQL5.7一键升级到MySQL8.0
话不多数,直接上脚本
#!/bin/bash
# Description: This script is designed to upgrade MySQL 5.7 to MySQL 8.0 (Binary Package Installation)
# Date: 2025-10-22
# ========================================================================
# Precautions before use:
# 1. Test in non-production environment first
# 2. Ensure complete database backup (data directory + logical backup)
# 3. Check application compatibility with MySQL 8.0
# 4. Execute as root user
# 5. Prepare MySQL 8.0 binary package (e.g., mysql-8.0.36-el7-x86_64.tar.gz)
# ========================================================================
# How to use:
# 1. Place MySQL 8.0 binary tar.gz in /tmp directory
# 2. chmod +x upgrade_mysql80_binary.sh
# 3. ./upgrade_mysql80_binary.sh
# ========================================================================set -e# ==============================================
# 请根据实际环境修改以下配置(二进制包安装相关路径)
# ==============================================
MYSQL_57_BASE_DIR="/usr/local/mysql" # 5.7二进制安装根目录
MYSQL_DATA_DIR="${MYSQL_57_BASE_DIR}/data" # 数据目录(通常在安装目录下)
MYSQL_80_TAR_PATH="/tmp/mysql-8.0.36-el7-x86_64.tar.gz" # 8.0二进制包路径
MYSQL_80_BASE_DIR="/usr/local/mysql-8.0" # 8.0安装目录
MYSQL_SOFT_LINK="/usr/local/mysql" # 软链接路径(指向当前版本)
MYSQL_CONF="/etc/my.cnf" # 配置文件路径
MYSQL_USER="mysql" # 运行MySQL的系统用户
MYSQL_GROUP="mysql" # 运行MySQL的系统组
MYSQL_ROOT_USER="root" # 数据库root用户
# ==============================================# 其他关键配置
BACKUP_DIR="/var/backups/mysql_upgrade"
LOG_FILE="/var/log/mysql_upgrade_$(date +%Y%m%d%H%M).log"
SERVICE_SCRIPT="${MYSQL_SOFT_LINK}/support-files/mysql.server" # 二进制包自带的服务脚本# 颜色代码
RED='\033[0;31m'
GREEN='\033[0;32m'
YELLOW='\033[0;33m'
NC='\033[0m' # No Color# 步骤0:初始化日志
exec > >(tee -a "$LOG_FILE") 2>&1
echo -e "${YELLOW}[0/13] 开始MySQL二进制包升级流程 $(date)${NC}"# 确认继续操作
confirm_continue() {read -p "$1 (y/n)? " choicecase "$choice" iny|Y) echo -e "${GREEN} 继续执行...${NC}";;*) echo -e "${YELLOW} 操作已取消${NC}"; exit 1;;esac
}# 获取MySQL root密码
get_mysql_password() {if [ -z "$MYSQL_ROOT_PASS" ]; thenread -s -p "输入MySQL root密码: " MYSQL_ROOT_PASSechofi
}# 验证二进制包文件
verify_80_tar() {if [ ! -f "$MYSQL_80_TAR_PATH" ]; thenecho -e "${RED} 错误:MySQL 8.0二进制包不存在($MYSQL_80_TAR_PATH)${NC}"exit 1fi# 验证文件格式(是否为tar.gz)if ! file "$MYSQL_80_TAR_PATH" | grep -q "gzip compressed"; thenecho -e "${RED} 错误:文件不是有效的gzip压缩包($MYSQL_80_TAR_PATH)${NC}"exit 1fi
}# 步骤1: 验证当前用户(必须为root)
echo -e "${YELLOW}[1/13] 验证执行用户${NC}"
if [ "$(id -u)" -ne 0 ]; thenecho -e "${RED} 错误:此脚本必须以root权限运行!${NC}"exit 1
fi
echo -e "${GREEN} 执行用户验证通过${NC}"# 步骤2: 验证当前MySQL版本(必须为5.7)
echo -e "${YELLOW}[2/13] 检查当前MySQL版本${NC}"
MYSQL_57_BIN="${MYSQL_57_BASE_DIR}/bin/mysql"
if [ ! -f "$MYSQL_57_BIN" ]; thenecho -e "${RED} 错误:未找到MySQL 5.7二进制文件($MYSQL_57_BIN)${NC}"exit 1
fi
CURRENT_VERSION=$("$MYSQL_57_BIN" -V 2>&1 | awk '{print $5}' | tr -d ,)
if [[ ! "$CURRENT_VERSION" =~ 5\.7 ]]; thenecho -e "${RED} 错误:当前MySQL版本($CURRENT_VERSION)不是5.7,终止升级!${NC}"exit 1
fi
echo -e "${GREEN} 当前版本验证通过: $CURRENT_VERSION${NC}"# 步骤3: 完整数据库备份(逻辑备份+数据目录备份)
echo -e "${YELLOW}[3/13] 执行全量备份${NC}"
mkdir -p "$BACKUP_DIR"
get_mysql_password# 逻辑备份(使用5.7的mysqldump)
echo -e "${YELLOW} 执行逻辑备份(全库+存储过程+事件)...${NC}"
MYSQLDUMP_57="${MYSQL_57_BASE_DIR}/bin/mysqldump"
"$MYSQLDUMP_57" -u"$MYSQL_ROOT_USER" -p"$MYSQL_ROOT_PASS" \--all-databases --routines --events --single-transaction > \"$BACKUP_DIR/full_backup_$(date +%F).sql"
if [ $? -eq 0 ]; thenecho -e "${GREEN} 逻辑备份成功: $BACKUP_DIR/full_backup_$(date +%F).sql${NC}"
elseecho -e "${RED} 错误:逻辑备份失败!${NC}"exit 1
fi# 数据目录备份(物理备份)
echo -e "${YELLOW} 执行数据目录备份...${NC}"
DATA_BACKUP_DIR="${BACKUP_DIR}/mysql_data_57_$(date +%s)"
cp -a "$MYSQL_DATA_DIR" "$DATA_BACKUP_DIR"
echo -e "${GREEN} 数据目录备份成功: $DATA_BACKUP_DIR${NC}"# 步骤4: 停止MySQL 5.7服务
echo -e "${YELLOW}[4/13] 停止MySQL 5.7服务${NC}"
if [ -f "$SERVICE_SCRIPT" ]; then"$SERVICE_SCRIPT" stop# 验证是否停止成功if pgrep -f "${MYSQL_57_BASE_DIR}/bin/mysqld" >/dev/null; thenecho -e "${RED} 错误:MySQL 5.7服务停止失败,强制终止进程...${NC}"pkill -f "${MYSQL_57_BASE_DIR}/bin/mysqld"fiecho -e "${GREEN} MySQL 5.7服务已停止${NC}"
elseecho -e "${RED} 错误:未找到服务脚本($SERVICE_SCRIPT)${NC}"exit 1
fi# 步骤5: 备份5.7配置和二进制目录
echo -e "${YELLOW}[5/13] 备份MySQL 5.7安装目录${NC}"
MV_57_DIR="${MYSQL_57_BASE_DIR}_57_backup_$(date +%s)"
mv "$MYSQL_57_BASE_DIR" "$MV_57_DIR"
echo -e "${GREEN} 5.7安装目录已备份至: $MV_57_DIR${NC}"# 步骤6: 安装MySQL 8.0二进制包
echo -e "${YELLOW}[6/13] 安装MySQL 8.0二进制包${NC}"
verify_80_tar# 解压二进制包
echo -e "${YELLOW} 解压MySQL 8.0二进制包...${NC}"
mkdir -p "$(dirname "$MYSQL_80_BASE_DIR")"
tar -zxf "$MYSQL_80_TAR_PATH" -C "$(dirname "$MYSQL_80_BASE_DIR")"
# 重命名解压后的目录(默认包名可能带版本号,统一为MYSQL_80_BASE_DIR)
TAR_EXTRACT_DIR=$(tar -ztf "$MYSQL_80_TAR_PATH" | head -1 | cut -d/ -f1)
mv "$(dirname "$MYSQL_80_BASE_DIR")/$TAR_EXTRACT_DIR" "$MYSQL_80_BASE_DIR"# 创建软链接(指向8.0版本)
ln -snf "$MYSQL_80_BASE_DIR" "$MYSQL_SOFT_LINK"
echo -e "${GREEN} 8.0二进制包安装完成,软链接: $MYSQL_SOFT_LINK -> $MYSQL_80_BASE_DIR${NC}"# 步骤7: 调整权限(关键!二进制包依赖mysql用户权限)
echo -e "${YELLOW}[7/13] 配置目录权限${NC}"
# 确保mysql用户组存在
if ! id -u "$MYSQL_USER" >/dev/null 2>&1; thengroupadd "$MYSQL_GROUP"useradd -r -g "$MYSQL_GROUP" "$MYSQL_USER"
fi
# 递归设置权限(数据目录+安装目录)
chown -R "$MYSQL_USER:$MYSQL_GROUP" "$MYSQL_80_BASE_DIR"
chown -R "$MYSQL_USER:$MYSQL_GROUP" "$MYSQL_DATA_DIR" # 数据目录保留原数据
chmod -R 755 "$MYSQL_80_BASE_DIR"
echo -e "${GREEN} 权限配置完成${NC}"# 步骤8: 调整配置文件(适配8.0兼容参数)
echo -e "${YELLOW}[8/13] 调整my.cnf配置(兼容8.0)${NC}"
# 备份原配置
cp "$MYSQL_CONF" "${MYSQL_CONF}_57_backup"# 添加/修改8.0兼容参数(关键:解决认证插件和语法兼容问题)
# 1. 禁用query_cache(8.0已移除)
sed -i '/query_cache/d' "$MYSQL_CONF"
# 2. 设置默认认证插件为5.7兼容模式(避免应用连接失败)
if ! grep -q "default_authentication_plugin" "$MYSQL_CONF"; thensed -i '/\[mysqld\]/a default_authentication_plugin=mysql_native_password' "$MYSQL_CONF"
elsesed -i 's/default_authentication_plugin=.*/default_authentication_plugin=mysql_native_password/' "$MYSQL_CONF"
fi
# 3. 移除8.0不支持的参数(如sql_mode中的NO_AUTO_CREATE_USER)
sed -i 's/NO_AUTO_CREATE_USER//' "$MYSQL_CONF"echo -e "${GREEN} 配置文件调整完成${NC}"# 步骤9: 启动MySQL 8.0并升级系统表
echo -e "${YELLOW}[9/13] 启动MySQL 8.0并升级系统表${NC}"
# 启动8.0服务(使用二进制包自带的服务脚本)
NEW_SERVICE_SCRIPT="${MYSQL_SOFT_LINK}/support-files/mysql.server"
"$NEW_SERVICE_SCRIPT" start
sleep 5 # 等待服务启动# 验证启动状态
if ! pgrep -f "${MYSQL_80_BASE_DIR}/bin/mysqld" >/dev/null; thenecho -e "${RED} 错误:MySQL 8.0启动失败,请检查日志(${MYSQL_DATA_DIR}/error.log)${NC}"exit 1
fi# 运行mysql_upgrade升级系统表(二进制包升级必须步骤)
echo -e "${YELLOW} 执行mysql_upgrade升级系统表...${NC}"
MYSQL_UPGRADE="${MYSQL_80_BASE_DIR}/bin/mysql_upgrade"
"$MYSQL_UPGRADE" -u"$MYSQL_ROOT_USER" -p"$MYSQL_ROOT_PASS"
if [ $? -eq 0 ]; thenecho -e "${GREEN} 系统表升级成功${NC}"
elseecho -e "${RED} 错误:系统表升级失败!${NC}"exit 1
fi# 步骤10: 重置root密码(处理8.0密码加密方式)
echo -e "${YELLOW}[10/13] 重置root密码(适配8.0加密)${NC}"
MYSQL_80_BIN="${MYSQL_80_BASE_DIR}/bin/mysql"
# 停止服务并启用免密登录
"$NEW_SERVICE_SCRIPT" stop
cp "$MYSQL_CONF" "${MYSQL_CONF}_temp"
sed -i '/\[mysqld\]/a skip-grant-tables' "$MYSQL_CONF"
"$NEW_SERVICE_SCRIPT" start
sleep 5# 重新设置密码(强制使用mysql_native_password)
"$MYSQL_80_BIN" -u"$MYSQL_ROOT_USER" <<EOF
FLUSH PRIVILEGES;
ALTER USER '${MYSQL_ROOT_USER}'@'localhost' IDENTIFIED WITH mysql_native_password BY '${MYSQL_ROOT_PASS}';
FLUSH PRIVILEGES;
EOF# 恢复配置并重启
"$NEW_SERVICE_SCRIPT" stop
mv "${MYSQL_CONF}_temp" "$MYSQL_CONF"
"$NEW_SERVICE_SCRIPT" start
sleep 5
echo -e "${GREEN} root密码重置完成${NC}"# 步骤11: 验证MySQL 8.0版本
echo -e "${YELLOW}[11/13] 验证升级后版本${NC}"
NEW_VERSION=$("$MYSQL_80_BIN" -V 2>&1 | awk '{print $5}' | tr -d ,)
if [[ "$NEW_VERSION" =~ 8\.0 ]]; thenecho -e "${GREEN} 版本验证通过:$NEW_VERSION${NC}"
elseecho -e "${RED} 错误:升级后版本不是8.0(当前:$NEW_VERSION)${NC}"exit 1
fi# 步骤12: 验证数据库可用性
echo -e "${YELLOW}[12/13] 验证数据库连接${NC}"
"$MYSQL_80_BIN" -u"$MYSQL_ROOT_USER" -p"$MYSQL_ROOT_PASS" -e "SELECT VERSION();" >/dev/null
if [ $? -eq 0 ]; thenecho -e "${GREEN} 数据库连接成功,升级后可用${NC}"
elseecho -e "${RED} 错误:无法连接升级后的数据库!${NC}"exit 1
fi# 步骤13: 升级完成提示
echo -e "${YELLOW}[13/13] 升级流程结束${NC}"
echo -e "${GREEN}====================================================${NC}"
echo -e "${GREEN} MySQL 5.7 -> 8.0 二进制包升级成功!${NC}"
echo -e "${GREEN}====================================================${NC}"
echo "关键信息:"
echo "1. 备份文件路径:$BACKUP_DIR"
echo "2. 升级日志:$LOG_FILE"
echo "3. 8.0安装目录:$MYSQL_80_BASE_DIR"
echo "4. 建议操作:"
echo " - 验证应用连接(注意认证插件兼容性)"
echo " - 检查错误日志:${MYSQL_DATA_DIR}/error.log"
echo " - 必要时优化8.0新特性(如innodb_dedicated_server)"