段落引用段落引用异步备机一般用于容灾数据库场景,往往需要快速完成容灾切换。本次记录以脚本完成异步备机切换实时备机的心得,便于快速完成数据库状态切换以及检查。
服务器名 | 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 "----------------------------------切换异步备机为主库成功----------------------------------"
文章
阅读量
获赞