注册
异步备机切换实时备机心得
专栏/培训园地/ 文章详情 /

异步备机切换实时备机心得

!!! 2025/05/13 57 1 0
摘要

异步备机切换实时备机

概述

段落引用段落引用异步备机一般用于容灾数据库场景,往往需要快速完成容灾切换。本次记录以脚本完成异步备机切换实时备机的心得,便于快速完成数据库状态切换以及检查。

环境说明

服务器名 IP地址 角色 实例名
DM_P 192.168.10.101 主库 GRP1_RT_1
DM_S1 192.168.10.102 实时备库 GRP1_RT_2
DM_AYNC 192.168.10.103 异步备库 DM_ASYNC

脚本说明

主备数据库切换脚本

#!/usr/bin/expect    #需先安装expect工具
set timeout 60    #设置超时时间
set dbname "GRP1_RT_2"   #自定义切换数据库名
set password "*******"    #数据库密码


spawn ${DB_HOME}/bin && ./dmmonitor  path=${DM_HOME}/dmmonitor.ini   #登录monitor交互


#monitor交互执行,切换主备数据库
expect "CLSN"
send "login\r"
expect {
  "用户名:" {send "SYSDBA\r"}
  "username:" {send "SYSDBA\r"}
}
expect {
  "密码:" {send "$password\r"}
  "password:" {send "$password\r"}
}
expect {
  "RECOVERY-->OPEN" {send "exit\r"}
  "失败" {send "exit\r"}
  "error" {send "exit\r"}
  "not in STANDBY" {send "exit\r"}
  "Login dmmonitor success" {send "switchover $dbname\r";exp_continue}
  "登录监视器成功" {send "switchover $dbname\r";exp_continue}
  "YES/NO" {send "YES\r";exp_continue}
}
exit

异步备库切换实时备机脚本

#基础信息
#!/bin/bash
username="SYSDBA"
password="*******"
DM_HOME=/dm8/dmdbms

#声明数组,数据库状态信息集合
declare -A GRP1_RT_1
declare -A GRP1_RT_2
declare -A DM_ASYNC

#多字符串比较
all_equal(){
    local target="$1"
    shift  # 移除第一个参数(目标值),剩余为待检查变量
    for var in "$@"; do
        [[ "\$var" != "$target" ]] && return 1
    done
    return 0
}



#获取数据库状态信息(status:监视器信息,arch:归档信息,imode:模式,istatus:数据库状态,wstatus:守护进程状态,inst:库运行状态,rstat:归档状态,atype:归档模式)
get_status(){
	ssh root@192.168.10.101 "${DM_HOME}/bin/dmmonitor path=${DM_HOME}/dmmonitor.ini"
	ssh root@192.168.10.101 "${DM_HOME}/bin/disql $username/$password 'SELECT ARCH_TYPE,ARCH_DEST,ARCH_STATUS FROM v\$arch_status;'"
	GRP1_RT_1["status"]=`ssh root@192.168.10.101 "${DM_HOME}/bin/dmmonitor path=${DM_HOME}/dmmonitor.in | grep ' GRP1_RT_1 '"`
	GRP1_RT_1["arch"]=`ssh root@192.168.10.101 "${DM_HOME}/bin/disql $username/$password 'SELECT ARCH_TYPE,ARCH_DEST,ARCH_STATUS FROM v\\$arch_status;'|grep ' GRP1_RT_1 '"`
	if [[ -n ${GRP1_RT_1["status"]} ]];then
		GRP1_RT_1["imode"]=`echo -en ${GRP1_RT_1["status"]}|awk  '{print $7}'`
		GRP1_RT_1["istatus"]=`echo -en ${GRP1_RT_1["status"]}|awk  '{print $6}'`
		GRP1_RT_1["wstatus"]=`echo -en ${GRP1_RT_1["status"]}|awk  '{print $3}'`
		GRP1_RT_1["inst"]=`echo -en ${GRP1_RT_1["status"]}|awk  '{print $4}'`
		GRP1_RT_1["rstat"]=`echo -en ${GRP1_RT_1["status"]}|awk  '{print $8}'`
	else
		echo "错误:未发现GRP1_RT_1同步信息!"
                for key in "${!GRP1_RT_1[@]}";do  
                        GRP1_RT_1[$key]=""
		done
        fi
	if [[ -n ${GRP1_RT_1["arch"]} ]];then
                GRP1_RT_1["atype"]=`echo -en ${GRP1_RT_1["arch"]}|awk  '{print $1}'`
	else
		echo "错误:未发现GRP1_RT_1归档信息!"	
		GRP1_RT_1["atype"]=""
	fi

	GRP1_RT_2["status"]=`ssh root@192.168.10.101 "${DM_HOME}/bin/dmmonitor path=${DM_HOME}/dmmonitor.in | grep ' GRP1_RT_2 '"`
	GRP1_RT_2["arch"]=`ssh root@192.168.10.101 "${DM_HOME}/bin/disql $username/$password 'SELECT ARCH_TYPE,ARCH_DEST,ARCH_STATUS FROM v\\$arch_status;'|grep ' GRP1_RT_2 '"`
	if [[ -n ${GRP1_RT_2["status"]} ]];then
                GRP1_RT_2["imode"]=`echo -en ${GRP1_RT_2["status"]}|awk  '{print $7}'`
                GRP1_RT_2["istatus"]=`echo -en ${GRP1_RT_2["status"]}|awk  '{print $6}'`
                GRP1_RT_2["wstatus"]=`echo -en ${GRP1_RT_2["status"]}|awk  '{print $3}'`
                GRP1_RT_2["inst"]=`echo -en ${GRP1_RT_2["status"]}|awk  '{print $4}'`
		GRP1_RT_2["rstat"]=`echo -en ${GRP1_RT_2["status"]}|awk  '{print $8}'`
        else
                echo "错误:未发现GRP1_RT_2状态!" 
                for key in "${!GRP1_RT_2[@]}";do  
                        GRP1_RT_2[$key]=""
		done
	fi
        if [[ -n ${GRP1_RT_2["arch"]} ]];then
                GRP1_RT_2["atype"]=`echo -en ${GRP1_RT_2["arch"]}|awk  '{print $1}'`
        else 
                echo "错误:未发现GRP1_RT_2归档信息!"
                GRP1_RT_2["atype"]=""
	fi

	GRP1_RT_2["status"]=`ssh root@192.168.10.101 "${DM_HOME}/bin/dmmonitor path=${DM_HOME}/dmmonitor.in | grep ' DM_ASYNC '"`
	GRP1_RT_2["arch"]=`ssh root@192.168.10.101 "${DM_HOME}/bin/disql $username/$password 'SELECT ARCH_TYPE,ARCH_DEST,ARCH_STATUS FROM v\\$arch_status;'|grep ' DM_ASYNC'"`
        if [[ -n ${DM_ASYNC["status"]} ]];then
        	DM_ASYNC["imode"]=`echo -en ${DM_ASYNC["status"]}|awk  '{print $7}'`
        	DM_ASYNC["istatus"]=`echo -en ${DM_ASYNC["status"]}|awk  '{print $6}'`
        	DM_ASYNC["wstatus"]=`echo -en ${DM_ASYNC["status"]}|awk  '{print $3}'`
        	DM_ASYNC["inst"]=`echo -en ${DM_ASYNC["status"]}|awk  '{print $4}'`
		DM_ASYNC["rstat"]=`echo -en ${DM_ASYNC["status"]}|awk  '{print $8}'`
        else
                echo "错误:未发现DM_ASYNC状态!"
                for key in "${!DM_ASYNC[@]}";do  
                        GRP1_RT_1[$key]=""
		done
	fi
        if [[ -n ${DM_ASYNC["arch"]} ]];then
                DM_ASYNC["atype"]=`echo -en ${DM_ASYNC["arch"]}|awk  '{print $1}'`
        else  
                echo "错误:未发现DM_ASYNC归档信息!"
                DM_ASYNC["atype"]=""
	fi


#数据库状态检查
check_status(){
	case $1 in
	 all|a)
	 	if ( !(all_equal "OPEN" ${GRP1_RT_1["wstatus"]} ${GRP1_RT_2["wstatus"]} ${DM_ASYNC["wstatus"]}) );then
			echo "错误:守护进程未开启!"
			return 1
		fi
		;;
	 all|b)
		if ( !(all_equal "OK" ${GRP1_RT_1["inst"]} ${GRP1_RT_2["inst"]} ${DM_ASYNC["inst"]}) );then
			echo "错误:数据库运行状态异常!"
			return 1
		fi
		;;
	 all|c)	
		if ( !(all_equal "OPEN" ${GRP1_RT_1["istatus"]} ${GRP1_RT_2["istatus"]} ${DM_ASYNC["istatus"]}) );then
			echo "错误:数据库状态未开启!"
			return 1
		fi
		;;
         all|d)
                if ( all_equal "INVALID" ${GRP1_RT_1["istatus"]} ${GRP1_RT_2["istatus"]} ${DM_ASYNC["istatus"]} );then
                        echo "错误:数据库同步状态异常!"
                        return 1
                fi
                ;;
	 e)
		if [[ ! (((${GRP1_RT_1["imode"]} -eq "PRIMARY" && ${GRP1_RT_2["imode"]} -eq "STANDBY") || (${GRP1_RT_1["imode"]} -eq "STANDBY" && ${GRP1_RT_2["imode"]} -eq"PRIMARY")) && (${DM_ASYNC["imode"]} -eq "STANDBY" && ${DM_ASYNC["atype"]} -eq "ASYNC")) ]];then
			echo "错误:数据库异步备机状态检查异常!"
			return 1
		fi
		;;
	 f)
		if [[ ! (((${GRP1_RT_1["imode"]} -eq "PRIMARY" && ${GRP1_RT_2["imode"]} -eq "STANDBY") || (${GRP1_RT_1["imode"]} -eq "STANDBY" && ${GRP1_RT_2["imode"]} -eq "PRIMARY")) && (${DM_ASYNC["imode"]} -eq "STANDBY" && ${DM_ASYNC["atype"]} -eq "REALTIME")) ]];then
			echo "错误:数据库实时备机状态检查异常!"
			return 1
	 	fi
		;;
	 g)
                if [[ ! (${GRP1_RT_1["imode"]} -eq "STANDBY" && ${GRP1_RT_2["imode"]} -eq "STANDBY" && ${DM_ASYNC["imode"]} -eq "PRIMARY") ]];then
                        echo "错误:数据库实时备机状态检查异常!"
                        return 1
		fi
		;;
	esac
	return 0
		
}


#获取数据库状态
echo "----------------------------------检测初始数据库状态----------------------------------"
get_status
if ( check_status "a" && check_status "a" && check_status "b" && check_status "c" && check_status "d" );then
	echo "数据库状态检查成功!"
else
	exit 1 
fi
if check_status "e";then
	echo "异步备机状态检查成功!"
else
	exit 1 
fi
#删除主库、备库异步归档
echo "----------------------------------修改主备库归档日志为实时归档----------------------------------"
#停止主备库守护进程
ssh root@192.168.10.101 "systemctl stop dmwatcher"
ssh root@192.168.10.102 "systemctl stop dmwatcher"
#修改主备库归档类型为实时归档
ssh root@192.168.10.101 "${DM_HOME}/bin/disql $username/$password 'ALTER DATABASE DELETE ARCHIVELOG 'DEST=DM_ASYNC;'"
ssh root@192.168.10.101 "${DM_HOME}/bin/disql $username/$password 'ALTER DATABASE ADD ARCHIVELOG 'DEST=DM_ASYNC, TYPE= REALTIME';'"
ssh root@192.168.10.102 "${DM_HOME}/bin/disql $username/$password 'ALTER DATABASE DELETE ARCHIVELOG 'DEST=DM_ASYNC;'"
ssh root@192.168.10.102 "${DM_HOME}/bin/disql $username/$password 'ALTER DATABASE ADD ARCHIVELOG 'DEST=DM_ASYNC, TYPE= REALTIME';'"
#重启主库、备库守护服务
ssh root@192.168.10.101 "systemctl restart dmwatcher"
ssh root@192.168.10.102 "systemctl restart dmwatcher"

get_status
if [[ ${DM_ASYNC["atype" -eq "REALTIME"]} ]];then
	echo "主备库归档日志修改为实时归档成功!"
else
	echo "错误:主备库归档日志修改为实时归档失败!"
	exit 1
fi

echo "-----------------------------------修改异步备机为实时备机----------------------------------"
#停止异步备机守护进程
ssh root@192.168.10.103 "systemctl stop dmwatcher"
#异步备机修改守护进程配置文件
ssh root@192.168.10.103 "sed -i 's/DW_TYPE  =  LOCAL/DW_TYPE  =  GLOBAL/g' /dm8/data/DAMENG/dmwatcher.ini"
ssh root@192.168.10.103 "sed -i 's/DW_MODE  =  MANUAL/DW_MODE  =  AUTO/g' /dm8/data/DAMENG/dmwatcher.ini"
#异步备机添加实时归档
cd /dm8/dmdbms/bin
ssh root@192.168.10.103 "disql $username/$password -E "ALTER DATABASE ADD ARCHIVELOG 'DEST=GRP1_RT_1, TYPE= REALTIME';""
ssh root@192.168.10.103 "disql $username/$password -E "ALTER DATABASE ADD ARCHIVELOG 'DEST=GRP1_RT_2, TYPE= REALTIME';""
#重启主库、备库守护服务
ssh root@192.168.10.101 "systemctl restart dmwatcher"
ssh root@192.168.10.102 "systemctl restart dmwatcher"
#异步备机重启守护进程
ssh root@192.168.10.103 "systemctl restart dmwatcher"

get_status
if ( check_status "a" && check_status "b" && check_status "c" && check_status "d" && check_status "f" );then
        echo "异步备机切换实时备机成功!"
else
        echo "错误:异步备机切换实时备机失败!"
        exit 1
fi

"----------------------------------切换异步备机为主库----------------------------------"
ssh root@192.168.10.101 "switch"    #调用主备切换脚本,见前文主备数据库切换脚本,switch为名称自定义
sleep 30
get_status

if ( check_status "a" && check_status "a" && check_status "b" && check_status "c" && check_status "d" && check_status "g" );then
        echo "异步备机切换为主库成功!"
else
        echo "错误:异步备机切换为主库失败!"
        exit 1
fi
echo "----------------------------------切换异步备机为主库成功----------------------------------"
评论
后发表回复

作者

文章

阅读量

获赞

扫一扫
联系客服