此脚本是专门用于MySQL8.0数据库主从复制架构下(基于GTID的复制)的自动切换的脚本,配置好相关基本信息(通用用户名,密码,主从数据库的复制用户,用户密码,IP地址,端口号)后,直接手动执行shell脚本即可完成MySQL主从架构下的自动切换功能,是计划内的数据库切换演练有利便捷的执行工具,可大大减少人工切换产生的误操作和切换时间问题。
脚本内容
该脚本名称为 mysql_switchover.sh
#!/bin/bash
# =============================================================================
# 基于GTID的MySQL 8.0 一主一从架构主从切换脚本 (支持不同端口)
# 版本: 1.0
# 修复内容: 表头输出问题、错误处理机制、GTID一致性检查逻辑
# =============================================================================
# >>>>>>>>>>>> 第一部分:脚本配置区域 (使用前请务必修改) <<<<<<<<<<<<
# 数据库连接凭证
MYSQL_USER="repluser"
MYSQL_PASS="repluser"
# 当前主从节点IP地址及端口
CURRENT_MASTER_HOST="10.2.8.4"
CURRENT_MASTER_PORT="3306"
CURRENT_SLAVE_HOST="10.2.8.4"
CURRENT_SLAVE_PORT="3307"
# 日志文件
LOG_FILE="/var/log/mysql_switchover.log"
LOCK_FILE="/tmp/mysql_switchover.lock"
# 连接超时时间(秒)
MYSQL_CONNECT_TIMEOUT=5
# >>>>>>>>>>>> 第二部分:核心函数定义 <<<<<<<<<<<<
# 日志记录函数
log() {
local LEVEL=$1
local MSG=$2
local TIMESTAMP=$(date "+%Y-%m-%d %H:%M:%S")
echo "[$TIMESTAMP] [$LEVEL] $MSG" | tee -a "$LOG_FILE"
}
# 错误处理与退出函数
error_exit() {
local MSG=$1
log "ERROR" "$MSG"
[ -f "$LOCK_FILE" ] && rm -f "$LOCK_FILE"
exit 1
}
# 通用的MySQL连接执行函数
mysql_exec() {
local HOST=$1
local PORT=$2
local SQL=$3
mysql -h"$HOST" -P"$PORT" -u"$MYSQL_USER" -p"$MYSQL_PASS" --connect-timeout=$MYSQL_CONNECT_TIMEOUT -e "$SQL" 2>/dev/null
}
# 获取MySQL单值结果 (专门用于获取单个值的函数)
get_mysql_value() {
local HOST=$1
local PORT=$2
local SQL=$3
mysql -h"$HOST" -P"$PORT" -u"$MYSQL_USER" -p"$MYSQL_PASS" --connect-timeout=$MYSQL_CONNECT_TIMEOUT -N -s -e "$SQL" 2>/dev/null | tail -1
}
# 检查MySQL实例是否可连接
check_mysql_connectivity() {
local HOST=$1
local PORT=$2
if mysql_exec "$HOST" "$PORT" "SELECT 1;" &> /dev/null; then
log "INFO" "成功连接到MySQL实例: $HOST:$PORT"
return 0
else
log "ERROR" "无法连接到MySQL实例: $HOST:$PORT"
return 1
fi
}
# 创建锁文件防止脚本重复运行
create_lockfile() {
if [ -f "$LOCK_FILE" ]; then
local LOCK_PID=$(cat "$LOCK_FILE")
if ps -p "$LOCK_PID" > /dev/null 2>&1; then
log "ERROR" "脚本已在运行中 (PID: $LOCK_PID),请勿重复执行"
exit 1
else
log "WARNING" "发现残留锁文件,清理后继续"
rm -f "$LOCK_FILE"
fi
fi
echo $$ > "$LOCK_FILE"
}
# 清理锁文件
cleanup_lockfile() {
[ -f "$LOCK_FILE" ] && rm -f "$LOCK_FILE"
}
# 检查复制延迟并等待追平(基于SHOW REPLICA STATUS)
wait_for_replica_catchup() {
local REPLICA_HOST=$1
local REPLICA_PORT=$2
local MAX_DELAY=60
local WAIT_TIMEOUT=300
local WAIT_STEP=5
local TOTAL_WAIT=0
log "INFO" "检查副本延迟并等待追平,最大容忍延迟: ${MAX_DELAY}秒,超时: ${WAIT_TIMEOUT}秒"
while [ $TOTAL_WAIT -lt $WAIT_TIMEOUT ]; do
# 修正:从SHOW REPLICA STATUS获取Seconds_Behind_Source值
local REPLICA_STATUS=$(mysql_exec "$REPLICA_HOST" "$REPLICA_PORT" "SHOW REPLICA STATUS\\G")
local DELAY=$(echo "$REPLICA_STATUS" | grep -i "Seconds_Behind_Source:" | awk '{print $2}')
# 处理空值和NULL情况
if [ "$DELAY" == "NULL" ] || [ -z "$DELAY" ]; then
log "ERROR" "无法获取副本延迟信息或复制已停止"
return 1
fi
# 确保DELAY是数字
if ! [[ "$DELAY" =~ ^[0-9]+$ ]]; then
log "ERROR" "获取的延迟值非数字: $DELAY"
return 1
fi
if [ "$DELAY" -eq 0 ]; then
log "INFO" "副本已完全追平,延迟: 0秒"
return 0
elif [ "$DELAY" -le $MAX_DELAY ]; then
log "INFO" "副本当前延迟: ${DELAY}秒,在容忍范围内"
break
else
log "INFO" "副本当前延迟: ${DELAY}秒,等待追平... 已等待 ${TOTAL_WAIT}秒"
sleep $WAIT_STEP
TOTAL_WAIT=$((TOTAL_WAIT + WAIT_STEP))
fi
done
if [ $TOTAL_WAIT -ge $WAIT_TIMEOUT ]; then
log "WARNING" "等待副本追平超时,当前延迟: ${DELAY}秒"
return 2
fi
return 0
}
# 检查复制状态 (使用MySQL 8.0的REPLICA语法)
check_replica_status() {
local HOST=$1
local PORT=$2
local STATUS=$(mysql_exec "$HOST" "$PORT" "SHOW REPLICA STATUS\\G")
if [ -z "$STATUS" ]; then
log "WARNING" "未找到复制状态信息,主机可能不是副本角色: $HOST:$PORT"
return 2
fi
local IO_THREAD=$(echo "$STATUS" | grep -i "Replica_IO_Running:" | awk '{print $2}')
local SQL_THREAD=$(echo "$STATUS" | grep -i "Replica_SQL_Running:" | awk '{print $2}')
local SECONDS_BEHIND=$(echo "$STATUS" | grep -i "Seconds_Behind_Source:" | awk '{print $2}')
if [[ "$IO_THREAD" == "Yes" ]] && [[ "$SQL_THREAD" == "Yes" ]]; then
log "INFO" "副本复制线程运行正常: $HOST:$PORT, 延迟: ${SECONDS_BEHIND:-N/A} 秒"
return 0
else
log "ERROR" "副本复制线程异常 - IO线程: $IO_THREAD, SQL线程: $SQL_THREAD"
return 1
fi
}
# 检查主从数据一致性 (基于GTID)
check_gtid_consistency() {
local MASTER_HOST=$1
local MASTER_PORT=$2
local SLAVE_HOST=$3
local SLAVE_PORT=$4
log "INFO" "开始检查主从GTID一致性..."
MASTER_GTID_SET=$(get_mysql_value "$MASTER_HOST" "$MASTER_PORT" "SELECT @@GLOBAL.GTID_EXECUTED;")
SLAVE_GTID_SET=$(get_mysql_value "$SLAVE_HOST" "$SLAVE_PORT" "SELECT @@GLOBAL.GTID_EXECUTED;")
if [ -z "$MASTER_GTID_SET" ] || [ -z "$SLAVE_GTID_SET" ]; then
log "ERROR" "获取主库或从库的GTID_EXECUTED失败"
return 1
fi
# 使用GTID_SUBTRACT函数检查从库是否缺失事务
local GTID_DIFF=$(get_mysql_value "$SLAVE_HOST" "$SLAVE_PORT" "SELECT GTID_SUBTRACT('$MASTER_GTID_SET', '$SLAVE_GTID_SET') AS DIFF;")
if [ -n "$GTID_DIFF" ] && [ "$GTID_DIFF" != "" ]; then
log "WARNING" "主从数据存在GTID差异: $GTID_DIFF"
return 2
else
log "INFO" "主从GTID一致性检查通过"
return 0
fi
}
# 设置实例为只读模式
set_read_only() {
local HOST=$1
local PORT=$2
local MODE=$3
if [ "$MODE" == "on" ]; then
log "INFO" "设置实例为只读模式: $HOST:$PORT"
mysql_exec "$HOST" "$PORT" "SET GLOBAL super_read_only=1, read_only=1;"
# 修复:使用改进的连接数查询,避免表头问题
local WRITE_CONNS=$(get_mysql_value "$HOST" "$PORT" "SELECT COUNT(*) FROM performance_schema.processlist where command not in ('Sleep','Binlog Dump','Binlog Dump GTID') AND USER NOT IN ('system user','event_scheduler') AND id <> connection_id();")
# 修复:添加数值检查,避免非数字值比较
if [ "$WRITE_CONNS" -gt 0 ] 2>/dev/null; then
log "WARNING" "发现 $WRITE_CONNS 个活跃写连接,建议处理"
else
log "INFO" "无活跃写连接或获取连接数失败"
fi
else
log "INFO" "关闭实例只读模式: $HOST:$PORT"
mysql_exec "$HOST" "$PORT" "SET GLOBAL read_only=0, super_read_only=0;"
fi
}
# 停止并重置复制
stop_and_reset_replica() {
local HOST=$1
local PORT=$2
log "INFO" "在主机上停止并重置复制: $HOST:$PORT"
mysql_exec "$HOST" "$PORT" "STOP REPLICA;"
mysql_exec "$HOST" "$PORT" "RESET REPLICA ALL;"
if [ $? -eq 0 ]; then
log "INFO" "成功停止并重置复制: $HOST:$PORT"
return 0
else
log "ERROR" "停止或重置复制操作失败: $HOST:$PORT"
return 1
fi
}
# 提升从库为新主库
promote_replica_to_source() {
local REPLICA_HOST=$1
local REPLICA_PORT=$2
log "INFO" "开始提升副本为新主库: $REPLICA_HOST:$REPLICA_PORT"
# 确保复制已停止并重置
stop_and_reset_replica "$REPLICA_HOST" "$REPLICA_PORT" || return 1
# 关闭只读模式,使其可写
set_read_only "$REPLICA_HOST" "$REPLICA_PORT" "off"
log "INFO" "副本提升为新主库操作完成: $REPLICA_HOST:$REPLICA_PORT"
}
# 配置旧主库作为新主库的从库
setup_old_source_as_replica() {
local OLD_MASTER_HOST=$1
local OLD_MASTER_PORT=$2
local NEW_MASTER_HOST=$3
local NEW_MASTER_PORT=$4
log "INFO" "开始配置旧主库作为新主库的副本: $OLD_MASTER_HOST:$OLD_MASTER_PORT -> $NEW_MASTER_HOST:$NEW_MASTER_PORT"
# 检查旧主库连接
check_mysql_connectivity "$OLD_MASTER_HOST" "$OLD_MASTER_PORT" || return 1
# 停止并重置复制(如果之前是主库)
stop_and_reset_replica "$OLD_MASTER_HOST" "$OLD_MASTER_PORT"
# 使用GTID自动定位配置主从复制
mysql_exec "$OLD_MASTER_HOST" "$OLD_MASTER_PORT" "CHANGE REPLICATION SOURCE TO SOURCE_HOST='$NEW_MASTER_HOST',SOURCE_PORT=$NEW_MASTER_PORT,SOURCE_USER='$MYSQL_USER',SOURCE_PASSWORD='$MYSQL_PASS',SOURCE_AUTO_POSITION=1,GET_SOURCE_PUBLIC_KEY=1; START REPLICA;"
if [ $? -eq 0 ]; then
log "INFO" "成功在旧主库上配置指向新主库的复制"
# 短暂等待后检查复制状态
sleep 5
if check_replica_status "$OLD_MASTER_HOST" "$OLD_MASTER_PORT"; then
log "INFO" "旧主库到新主库的复制状态正常"
return 0
else
log "WARNING" "旧主库到新主库的复制状态异常"
return 2
fi
else
log "ERROR" "在旧主库上配置复制关系失败"
return 1
fi
}
# 切换后验证函数 - 完全重写版
verify_switchover_result() {
local NEW_SOURCE_HOST=$1
local NEW_SOURCE_PORT=$2
local OLD_SOURCE_HOST=$3
local OLD_SOURCE_PORT=$4
log "INFO" "开始验证切换结果..."
# 创建临时测试数据库(使用更安全的命名)
local TEST_DB="test_switchover_$(date +%s)"
# 第一层验证:创建数据库
local CREATE_DB_SQL="CREATE DATABASE IF NOT EXISTS $TEST_DB"
if ! mysql_exec "$NEW_SOURCE_HOST" "$NEW_SOURCE_PORT" "$CREATE_DB_SQL"; then
log "ERROR" "新主库创建数据库测试失败: $NEW_SOURCE_HOST:$NEW_SOURCE_PORT"
return 1
fi
log "INFO" "新主库创建数据库测试通过: $NEW_SOURCE_HOST:$NEW_SOURCE_PORT"
# 第二层验证:创建表
# 对于复杂的SQL,使用heredoc最安全
local CREATE_TABLE_SQL=$(cat <<SQL
CREATE TABLE $TEST_DB.verify_switchover (id INT PRIMARY KEY, test_time TIMESTAMP)
SQL
)
if ! mysql_exec "$NEW_SOURCE_HOST" "$NEW_SOURCE_PORT" "$CREATE_TABLE_SQL"; then
log "ERROR" "新主库创建表测试失败"
mysql_exec "$NEW_SOURCE_HOST" "$NEW_SOURCE_PORT" "DROP DATABASE IF EXISTS $TEST_DB"
return 1
fi
# 第三层验证:插入数据
local INSERT_SQL=$(cat <<SQL
INSERT INTO $TEST_DB.verify_switchover VALUES (1, NOW())
SQL
)
if ! mysql_exec "$NEW_SOURCE_HOST" "$NEW_SOURCE_PORT" "$INSERT_SQL"; then
log "ERROR" "新主库插入数据测试失败"
mysql_exec "$NEW_SOURCE_HOST" "$NEW_SOURCE_PORT" "DROP DATABASE IF EXISTS $TEST_DB"
return 1
fi
log "INFO" "新主库写测试完全通过: $NEW_SOURCE_HOST:$NEW_SOURCE_PORT"
# 清理测试数据
mysql_exec "$NEW_SOURCE_HOST" "$NEW_SOURCE_PORT" "DROP DATABASE IF EXISTS $TEST_DB"
# 验证旧主库复制状态
if check_mysql_connectivity "$OLD_SOURCE_HOST" "$OLD_SOURCE_PORT"; then
sleep 3
if check_replica_status "$OLD_SOURCE_HOST" "$OLD_SOURCE_PORT"; then
log "INFO" "旧主库到新主库的复制状态正常"
else
log "WARNING" "旧主库到新主库的复制状态异常,需人工检查"
return 2
fi
else
log "INFO" "旧主库当前不可达,复制状态略过检查"
fi
log "INFO" "切换验证完成"
return 0
}
# >>>>>>>>>>>> 第三部分:切换主流程 <<<<<<<<<<<<
# 切换函数
switchover() {
log "INFO" "开始主从切换流程..."
# 1. 前置检查
log "INFO" "步骤1: 执行前置检查"
check_mysql_connectivity "$CURRENT_MASTER_HOST" "$CURRENT_MASTER_PORT" || error_exit "原主库无法连接,切换中止"
check_mysql_connectivity "$CURRENT_SLAVE_HOST" "$CURRENT_SLAVE_PORT" || error_exit "从库无法连接,切换中止"
check_replica_status "$CURRENT_SLAVE_HOST" "$CURRENT_SLAVE_PORT" || error_exit "从库复制状态异常,切换中止"
# 2. 检查数据一致性
log "INFO" "步骤2: 检查主从数据一致性"
check_gtid_consistency "$CURRENT_MASTER_HOST" "$CURRENT_MASTER_PORT" "$CURRENT_SLAVE_HOST" "$CURRENT_SLAVE_PORT"
local CONSISTENCY_RESULT=$?
if [ $CONSISTENCY_RESULT -eq 1 ]; then
error_exit "GTID一致性检查失败,切换中止"
elif [ $CONSISTENCY_RESULT -eq 2 ]; then
log "WARNING" "主从数据存在差异,请确认是否继续切换? (y/N)"
read -t 30 user_input
if [[ ! "$user_input" =~ ^[Yy]$ ]]; then
log "INFO" "用户取消切换操作"
exit 1
fi
log "INFO" "用户确认继续切换"
fi
# 3. 设置原主库为只读
log "INFO" "步骤3: 设置原主库为只读模式"
set_read_only "$CURRENT_MASTER_HOST" "$CURRENT_MASTER_PORT" "on"
# 4. 等待从库追平延迟
log "INFO" "步骤4: 检查从库复制延迟"
wait_for_replica_catchup "$CURRENT_SLAVE_HOST" "$CURRENT_SLAVE_PORT"
local CATCHUP_RESULT=$?
if [ $CATCHUP_RESULT -eq 1 ]; then
error_exit "检查副本延迟时发生错误"
elif [ $CATCHUP_RESULT -eq 2 ]; then
log "WARNING" "从库延迟较大,请确认是否继续切换? (y/N)"
read -t 30 user_input
if [[ ! "$user_input" =~ ^[Yy]$ ]]; then
# 恢复原主库可写状态
set_read_only "$CURRENT_MASTER_HOST" "$CURRENT_MASTER_PORT" "off"
log "INFO" "用户取消切换操作,已恢复原主库写权限"
exit 1
fi
log "INFO" "用户确认继续切换"
fi
# 5. 提升从库为新主库
log "INFO" "步骤5: 提升从库为新主库"
promote_replica_to_source "$CURRENT_SLAVE_HOST" "$CURRENT_SLAVE_PORT" || error_exit "提升从库失败"
# 6. 配置旧主库为新从库(加强错误处理)
log "INFO" "步骤6: 配置旧主库为新从库"
if ! setup_old_source_as_replica "$CURRENT_MASTER_HOST" "$CURRENT_MASTER_PORT" "$CURRENT_SLAVE_HOST" "$CURRENT_SLAVE_PORT"; then
log "WARNING" "配置旧主库为新从库失败,尝试备用方案..."
# 备用方案:重置GTID并重试
local NEW_MASTER_GTID=$(get_mysql_value "$CURRENT_SLAVE_HOST" "$CURRENT_SLAVE_PORT" "SELECT @@GLOBAL.GTID_EXECUTED;")
if [ -n "$NEW_MASTER_GTID" ]; then
log "INFO" "尝试备用GTID同步方案"
mysql_exec "$CURRENT_MASTER_HOST" "$CURRENT_MASTER_PORT" "STOP REPLICA; RESET REPLICA ALL;"
mysql_exec "$CURRENT_MASTER_HOST" "$CURRENT_MASTER_PORT" "SET GLOBAL gtid_purged='$NEW_MASTER_GTID';"
if setup_old_source_as_replica "$CURRENT_MASTER_HOST" "$CURRENT_MASTER_PORT" "$CURRENT_SLAVE_HOST" "$CURRENT_SLAVE_PORT"; then
log "INFO" "备用方案配置成功"
else
log "ERROR" "备用方案也失败,需要手动干预"
return 2
fi
else
log "ERROR" "无法获取新主库GTID,备用方案无法执行"
return 2
fi
fi
# 7. 最终验证(必须成功)
log "INFO" "步骤7: 执行切换后验证"
if verify_switchover_result "$CURRENT_SLAVE_HOST" "$CURRENT_SLAVE_PORT" "$CURRENT_MASTER_HOST" "$CURRENT_MASTER_PORT"; then
log "INFO" "切换验证通过"
else
error_exit "切换验证失败,新主库可能不可用"
fi
log "INFO" "主从切换流程全部完成!新主库: $CURRENT_SLAVE_HOST:$CURRENT_SLAVE_PORT"
}
# >>>>>>>>>>>> 第四部分:脚本入口 <<<<<<<<<<<<
# 主执行逻辑
main() {
# 创建锁文件
create_lockfile
trap cleanup_lockfile EXIT
log "INFO" "==== MySQL主从切换脚本开始执行 ===="
log "INFO" "原主库: $CURRENT_MASTER_HOST:$CURRENT_MASTER_PORT"
log "INFO" "原从库: $CURRENT_SLAVE_HOST:$CURRENT_SLAVE_PORT"
switchover
local result=$?
if [ $result -eq 0 ]; then
log "INFO" "脚本执行成功"
else
log "ERROR" "脚本执行过程中遇到错误"
fi
log "INFO" "==== MySQL主从切换脚本执行结束 ===="
exit $result
}
# 脚本执行入口
main
重点说明
-
版本限制(MySQL8.0.23及以上)
该脚本测试时使用的MySQL版本为8.0.41,主从架构搭建时是采用新的 CHANGE REPLICATION SOURCE TO 语法创建的,在脚本获取相关信息时也是采用 SHOW REPLICA STATUS\G方式获取,由于新的语法是官方从8.0.23版本才进行调整的,故本脚本限制的版本必须是大于等于MySQL8.0.23。
-
复制限制(GTID模式)
脚本中测试环境复制架构采用的是基于GTID的复制方式,故如果主从架构是基于binlog+position的老方式复制是不适用的。
-
额外说明
在使用该脚本前,需要对脚本中的开始位置(第一部分:脚本配置区域)进行提前配置好,根据实际环境(复制用户,IP地址,端口,日志路径)进行相关配置才可以运行。
使用方法
- 保存脚本并赋权
chmod +x mysql_switchover.sh
- 手工执行脚本
./mysql_switchover.sh
- 执行过程:
[root@VM-8-4-opencloudos ~]# ./mysql_switchover.sh
[2025-11-28 17:22:27] [INFO] ==== MySQL主从切换脚本开始执行 ====
[2025-11-28 17:22:27] [INFO] 原主库: 10.2.8.4:3306
[2025-11-28 17:22:27] [INFO] 原从库: 10.2.8.4:3307
[2025-11-28 17:22:27] [INFO] 开始主从切换流程...
[2025-11-28 17:22:27] [INFO] 步骤1: 执行前置检查
[2025-11-28 17:22:27] [INFO] 成功连接到MySQL实例: 10.2.8.4:3306
[2025-11-28 17:22:27] [INFO] 成功连接到MySQL实例: 10.2.8.4:3307
[2025-11-28 17:22:27] [INFO] 副本复制线程运行正常: 10.2.8.4:3307, 延迟: 0 秒
[2025-11-28 17:22:27] [INFO] 步骤2: 检查主从数据一致性
[2025-11-28 17:22:27] [INFO] 开始检查主从GTID一致性...
[2025-11-28 17:22:27] [INFO] 主从GTID一致性检查通过
[2025-11-28 17:22:27] [INFO] 步骤3: 设置原主库为只读模式
[2025-11-28 17:22:27] [INFO] 设置实例为只读模式: 10.2.8.4:3306
[2025-11-28 17:22:28] [INFO] 无活跃写连接或获取连接数失败
[2025-11-28 17:22:28] [INFO] 步骤4: 检查从库复制延迟
[2025-11-28 17:22:28] [INFO] 检查副本延迟并等待追平,最大容忍延迟: 60秒,超时: 300秒
[2025-11-28 17:22:28] [INFO] 副本已完全追平,延迟: 0秒
[2025-11-28 17:22:28] [INFO] 步骤5: 提升从库为新主库
[2025-11-28 17:22:28] [INFO] 开始提升副本为新主库: 10.2.8.4:3307
[2025-11-28 17:22:28] [INFO] 在主机上停止并重置复制: 10.2.8.4:3307
[2025-11-28 17:22:28] [INFO] 成功停止并重置复制: 10.2.8.4:3307
[2025-11-28 17:22:28] [INFO] 关闭实例只读模式: 10.2.8.4:3307
[2025-11-28 17:22:28] [INFO] 副本提升为新主库操作完成: 10.2.8.4:3307
[2025-11-28 17:22:28] [INFO] 步骤6: 配置旧主库为新从库
[2025-11-28 17:22:28] [INFO] 开始配置旧主库作为新主库的副本: 10.2.8.4:3306 -> 10.2.8.4:3307
[2025-11-28 17:22:29] [INFO] 成功连接到MySQL实例: 10.2.8.4:3306
[2025-11-28 17:22:29] [INFO] 在主机上停止并重置复制: 10.2.8.4:3306
[2025-11-28 17:22:29] [INFO] 成功停止并重置复制: 10.2.8.4:3306
[2025-11-28 17:22:30] [INFO] 成功在旧主库上配置指向新主库的复制
[2025-11-28 17:22:36] [INFO] 副本复制线程运行正常: 10.2.8.4:3306, 延迟: 0 秒
[2025-11-28 17:22:36] [INFO] 旧主库到新主库的复制状态正常
[2025-11-28 17:22:36] [INFO] 步骤7: 执行切换后验证
[2025-11-28 17:22:36] [INFO] 开始验证切换结果...
[2025-11-28 17:22:36] [INFO] 新主库创建数据库测试通过: 10.2.8.4:3307
[2025-11-28 17:22:39] [INFO] 新主库写测试完全通过: 10.2.8.4:3307
[2025-11-28 17:22:40] [INFO] 成功连接到MySQL实例: 10.2.8.4:3306
[2025-11-28 17:22:44] [INFO] 副本复制线程运行正常: 10.2.8.4:3306, 延迟: 0 秒
[2025-11-28 17:22:44] [INFO] 旧主库到新主库的复制状态正常
[2025-11-28 17:22:44] [INFO] 切换验证完成
[2025-11-28 17:22:44] [INFO] 切换验证通过
[2025-11-28 17:22:44] [INFO] 主从切换流程全部完成!新主库: 10.2.8.4:3307
[2025-11-28 17:22:44] [INFO] 脚本执行成功
[2025-11-28 17:22:44] [INFO] ==== MySQL主从切换脚本执行结束 ====
[root@VM-8-4-opencloudos ~]#
说明:本示例测试环境为:
- MySQL主库:
10.2.8.4 端口为 3306
- MySQL从库:
10.2.8.4 端口为 3307
- 复制用户:
repluser。 本示例中复制用户赋权为所有权限,实际用户可根据情况更换,但必须有相关权限才行(设置参数read_only,复制权限replication slave,建库,建表,增删改查数据,表和库)
示例截图:

总结
此脚本根据实际环境进行参数配置后,可以自动化的进行针对Shell主从环境的切换演练,并可以适当的通过脚本中内容进行调整,比如可以自定义设置从库延迟的时间,是否可以接受从库延迟等方式。通过反复测试可以正常运行,基本可以替代手工切换过程中的状态检查和繁琐的确认环节,从而有效减少人为失误。
|