ORACLE 12C ADG 之二十一 ( ADG 配置VIP )

  1. 編寫ip切換腳本 - 主機 & 备机
[oracle@DB196 shell]$ mkdir -p /home/oracle/log/
[oracle@DB196 shell]$ pwd
/u01/app/oracle/product/12.2.0/db_1/shell
[oracle@DB196 shell]$ ls
  myip.sh

[oracle@DB196 shell]$ cat myip.sh

#!/bin/bash

logfile=/home/oracle/log/vip_switch.log 
echo ''  | tee -a $logfile

if [ $# -ne 4 ]
then
  echo Usage: $0 add/del hostname ssh_port vip | tee -a $logfile
  exit 1;
fi

action=$1
hostname=$2
ssh_port=$3
vip=$4

function get_gateway {
if [ $# -ne 2 ] ; then
  return 1
fi

local v_str="ssh -p $1 root@$2 ip route show | grep default | awk -F' ' '{print \$3}'"
echo $(date "+%Y-%m-%d %H:%M:%S") "------------------>" $v_str >> $logfile
local tmp_gateway=$(ssh -p $1 root@$2 ip route show | grep default | awk -F' ' '{print $3}')
echo $tmp_gateway
}

function get_linkname {
if [ $# -ne 2 ] ; then
  return 1
fi

local v_str="ssh -p $1 root@$2 ip link | grep -E '^[0-9]' | grep BROADCAST | awk -F': ' '{print \$2}'"
echo $(date "+%Y-%m-%d %H:%M:%S") "------------------>" $v_str >> $logfile
local tmp_linkname=$(ssh -p $1 root@$2 ip link | grep -E '^[0-9]' | grep BROADCAST | awk -F': ' '{print $2}')
echo $tmp_linkname
}

function get_netport {
if [ $# -ne 3 ] ; then
  return 1
fi

local v_str="ssh -p $1 root@$2 ip addr show $3 | grep $3 | grep -v 'secondary' | grep 'brd' | grep 'scope global' | awk -F' ' '{print \$2}' | awk -F/ '{print \$2}'"
echo $(date "+%Y-%m-%d %H:%M:%S") "------------------>" $v_str >> $logfile
local tmp_netport=$(ssh -p $1 root@$2 ip addr show $3 | grep $3 | grep -v 'secondary' | grep 'brd' | grep 'scope global' | awk -F' ' '{print $2}' | awk -F/ '{print $2}')
echo $tmp_netport
}

function get_current_vip {
if [ $# -ne 4 ] ; then
  return 1
fi

local v_str="ssh -p $1 root@$2 ip addr show $3 | grep $3 | grep 'scope global'  | grep $4 | awk -F' ' '{print \$2}' | awk -F/ '{print \$1}'"
echo $(date "+%Y-%m-%d %H:%M:%S") "------------------>" $v_str >> $logfile
local tmp_current_vip=$(ssh -p $1 root@$2 ip addr show $3 | grep $3 | grep 'scope global'  | grep $4 | awk -F' ' '{print $2}'  | awk -F/ '{print $1}')
echo $tmp_current_vip
}

function set_vip {
if [ $# -ne 6 ] ; then
  return 1
fi

local v_str="ssh -p $1 root@$2 ip addr $3 $4/$5 dev $6"
echo $(date "+%Y-%m-%d %H:%M:%S") "------------------>" $v_str | tee -a $logfile
ssh -p $1 root@$2 ip addr $3 $4/$5 dev $6
}

function send_ping {
if [ $# -ne 4 ] ; then
  return 1
fi

local v_str="ssh -p $1 root@$2 ping $3 -c 1 -I $4 1>/dev/null"
echo $(date "+%Y-%m-%d %H:%M:%S") "------------------>" $v_str | tee -a $logfile
ssh -p $1 root@$2 ping $3 -c 1 -I $4 1>/dev/null
}

function send_arp {
if [ $# -ne 4 ] ; then
  return 1
fi

local v_str="ssh -p $1 root@$2 /sbin/arping -I $3 -f $4 -s $5 -w 2 1>/dev/null"
echo $(date "+%Y-%m-%d %H:%M:%S") "------------------>" $v_str | tee -a $logfile
ssh -p $1 root@$2 /sbin/arping -I $3 -f $4 -s $5 -q -w 2 1>/dev/null;
}

gateway=$(get_gateway $ssh_port $hostname) 
if [ $? = 1 ] ; then
  exit 1;
fi
echo $(date "+%Y-%m-%d %H:%M:%S") "------------------- gateway = [$gateway]" | tee -a $logfile

linkname=$(get_linkname $ssh_port $hostname)
if [ $? = 1 ] ; then
  exit 1;
fi
echo $(date "+%Y-%m-%d %H:%M:%S") "------------------- linkname = [$linkname]" | tee -a $logfile

netport=$(get_netport $ssh_port $hostname $linkname)
if [ $? = 1 ] ; then
  exit 1;
fi
echo $(date "+%Y-%m-%d %H:%M:%S") "------------------- netport = [$netport]" | tee -a $logfile

current_vip=$(get_current_vip $ssh_port $hostname $linkname $vip)
if [ $? = 1 ] ; then
  exit 1;
fi
echo $(date "+%Y-%m-%d %H:%M:%S") "------------------- current_vip = [$current_vip]" | tee -a $logfile

if [ "${current_vip}" = "$vip" ]; then
     echo $(date "+%Y-%m-%d %H:%M:%S") "------------------- current_vip is [${current_vip}] = [$vip]" | tee -a $logfile

     if [ "$action" = "add" ]; then
        send_ping $ssh_port $hostname $gateway $vip      
        echo $(date "+%Y-%m-%d %H:%M:%S") "------------------- [ $0 $@ ] NONE " | tee -a $logfile  
        exit 0;
     elif [ "$action" = "del" ]; then
        set_vip $ssh_port $hostname $action $vip $netport $linkname            
        exit $?;
     else
        exit 0;
     fi 
else
     echo $(date "+%Y-%m-%d %H:%M:%S") "------------------- current_vip is [${current_vip}] !=[$vip]" | tee -a $logfile
     
     if [ "$action" = "add" ]; then
         set_vip $ssh_port $hostname $action $vip $netport $linkname              
         send_arp $ssh_port $hostname $linkname $gateway $vip
         exit 0;
     elif [ "$action" = "del" ]; then
         echo $(date "+%Y-%m-%d %H:%M:%S") "------------------- [ $0 $@ ] NONE " | tee -a $logfile
         exit 0;
     else
        exit 0;
     fi
fi
[oracle@DB196 shell]$ chmod u+x myip.sh
  1. 创建 myip_user (主庫 sys下)
begin
  dbms_scheduler.create_credential
  (
    credential_name => 'myip_user',
    username        => 'oracle',
    password        => 'xag#1234'
  );
end;
  1. 創建oracle 中 調用 shell 腳本 scheduler job (主庫 sys下)
begin                           
 dbms_scheduler.create_job(job_name => 'IP_JOB', job_type => 'EXECUTABLE',number_of_arguments => 4
 ,job_action => '/u01/app/oracle/product/12.2.0/db_1/shell/myip.sh'
 ,comments => 'ENABLE VIP(IP_JOB)',auto_drop => false);
end;

4.创建 my_ip_conig 存储过程

CREATE OR REPLACE PROCEDURE my_ip_conig(p_action in varchar2,p_hostname in varchar2,p_sshport in varchar2,p_vip in varchar2)
IS
BEGIN
  dbms_scheduler.set_job_argument_value(job_name => 'IP_JOB',argument_position => 1,argument_value => p_action);
  dbms_scheduler.set_job_argument_value(job_name => 'IP_JOB',argument_position => 2,argument_value => p_hostname);

  dbms_scheduler.set_job_argument_value(job_name => 'IP_JOB',argument_position => 3,argument_value => p_sshport);
  dbms_scheduler.set_job_argument_value(job_name => 'IP_JOB',argument_position => 4,argument_value => p_vip);

  --dbms_scheduler.enable('IP_JOB');
  dbms_scheduler.run_job('IP_JOB');

END;   
  1. 创建 pr_vip_check 存储过程
create or replace procedure pr_vip_check as
 v_pir_host varchar2(30);
 v_stby_status varchar2(30);
 v_database_role varchar2(30);
begin
  select nvl(max(database_role),'NONE') into v_database_role from v$database t where t.DATAGUARD_BROKER='ENABLED';
  if v_database_role='PRIMARY' then
     select utl_inaddr.get_host_name into v_pir_host from dual;
     select nvl(max(t."STATUS"),'NONE') into v_stby_status from v$archive_dest_status t where t.STATUS !='INACTIVE' and t.TYPE='PHYSICAL';

     if v_pir_host='xag120' and v_stby_status='VALID' then
        my_ip_conig('del','xag120','22','192.168.40.123');
        my_ip_conig('add','xag121','22','192.168.40.123');

        my_ip_conig('del','xag121','22','192.168.40.122');
        my_ip_conig('add','xag120','22','192.168.40.122');
     elsif v_pir_host='xag120' and v_stby_status!='VALID' then

        my_ip_conig('del','xag121','22','192.168.40.123');
        my_ip_conig('add','xag120','22','192.168.40.123');

        my_ip_conig('del','xag121','22','192.168.40.122');
        my_ip_conig('add','xag120','22','192.168.40.122');

     elsif v_pir_host='xag121' and v_stby_status='VALID' then
        my_ip_conig('del','xag121','22','192.168.40.123');
        my_ip_conig('add','xag120','22','192.168.40.123');

        my_ip_conig('del','xag120','22','192.168.40.122');
        my_ip_conig('add','xag121','22','192.168.40.122');
     elsif v_pir_host='xag121' and v_stby_status!='VALID' then

        my_ip_conig('del','xag120','22','192.168.40.123');
        my_ip_conig('add','xag121','22','192.168.40.123');

        my_ip_conig('del','xag120','22','192.168.40.122');
        my_ip_conig('add','xag121','22','192.168.40.122');

     end if;
  else
     null;
  end if;
end;
  1. 測試腳本
   begin
       pr_vip_check; 
   end;
  1. 創建db啟動或db角色改變時觸發器
create or replace TRIGGER tr_vip_check
after startup or db_role_change on database
begin
  pr_vip_check;
end;
  1. 創建vip 輪詢檢查的job
begin
   dbms_scheduler.create_job(
   job_name => 'VIP_CHECK', --job名
   job_type => 'STORED_PROCEDURE', --job类型
   job_action => 'pr_vip_check', --存储过程名
   start_date => sysdate, --开始执行时间
   repeat_interval => 'FREQ=SECONDLY;INTERVAL=60', --下次执行时间,每60秒执行存储过程pc_sam
   comments => 'CHECK VIP', --注释
   auto_drop => false, --job禁用后是否自动删除
 enabled => true);
 end;
  1. 創建scheduler job 查詢視圖
CREATE OR REPLACE VIEW V_XAG_JOB2 AS
SELECT JOB_NAME,JOB_ACTION job,to_char(START_DATE,'yyyy-mm-dd hh24:mi:ss') as START_DATE
 ,REPEAT_INTERVAL,ENABLED,to_char(LAST_START_DATE,'yyyy-mm-dd hh24:mi:ss') as LAST_START_DATE
 ,to_char(NEXT_RUN_DATE,'yyyy-mm-dd hh24:mi:ss') as NEXT_RUN_DATE
 ,COMMENTS
 FROM user_scheduler_jobs order by JOB_NAME;

10.查詢

[oracle@xag120 ~]$ sql / as sysdba

SQL> set sqlformat ansiconsole

SQL> select * from V_XAG_JOB2 where job_name in('IP_JOB','VIP_CHECK');
JOB_NAME   JOB                                                  START_DATE           REPEAT_INTERVAL            ENABLED  LAST_START_DATE      NEXT_RUN_DATE        COMMENTS            
IP_JOB     /u01/app/oracle/product/12.2.0.1/db_1/shell/myip.sh                                                  FALSE                                              ENABLE VIP(IP_JOB)  
VIP_CHECK  pr_vip_check                                         2020-07-18 23:00:10  FREQ=SECONDLY;INTERVAL=60  TRUE     2020-07-18 23:03:10  2020-07-18 23:04:10  CHECK VIP 

Oracle DBMS_SCHEDULER调用操作系统脚本
DBMS_SCHEDULER credential

Linux ip 命令

你可能感兴趣的:(ORACLE 12C ADG 之二十一 ( ADG 配置VIP ))