Oracle RAC service Fail Back 问题解析

 

对于Oracle RAC中的service的fail over 存在这样的疑问,例如 存在一个service 有一个preferred 的instance 和一个available 的instance,当preferred instance失败时service failover到available instance上,当这个preferred instance的实例恢复时该RAC SERVICE是否会fail back 回到preferred instance ,还是原地不动?

 

对于这个问题 官方文档有明确的说明:

 

https://docs.oracle.com/cd/E11882_01/rac.112/e41960/hafeats.htm#RACAD076

 

When a service moves to an available instance, Oracle Database does not move the service back to the preferred instance when the preferred instance restarts because:

  • The service is running on the desired number of instances.
  • Maintaining the service on the current instance provides a higher level of service availability.
  • Not moving the service back to the initial preferred instance prevents a second outage.

You can, however, easily automate fail back to the preferred instance by using FAN callouts.

 

即oracle认为 当这种场景时不应当立刻做fail back 否则可能造成再次outage ,同时目前的情况也基本符合当初用户对该服务定义的需求。

 

对于有用户确实需要自动fail back回去的可以参考Ilmar Kerm DB blog 《Scipt to automatically move RAC 11gR2 services back to preferred instances》中的脚本:

 

 
#!/bin/bash
#
# GI callout script to catch INSTANCE up event from clusterware and relocate services to preferred instance
# Copy or symlink this script to $GRID_HOME/racg/usrco
# Tested on Oracle Linux 5.8 with 11.2.0.3 Oracle Grid Infrastructure and 11.2.0.2 & 11.2.0.3 Oracle Database Enterprise Edition
# 2012 Ilmar Kerm ilmar.kerm@gmail.com
#
 
LOGFILE=/u02/app/oracle/grid_callout/log.txt
SCRIPTDIR=`dirname $0`
 
# Determine grid home
if [[ "${SCRIPTDIR:(-11)}" == "/racg/usrco" ]]; then
  CRS_HOME=""${SCRIPTDIR:0:$(( ${#SCRIPTDIR} - 11 ))}""
  export CRS_HOME
fi
 
# Only execute script for INSTANCE events
if [ "$1" != "INSTANCE" ]; then
  exit 0
fi
 
STATUS=""
DATABASE=""
INSTANCE=""
 
# Parse input arguments
args=("$@")
for arg in ${args[@]}; do
  if [[ "$arg" == *=* ]]; then
    KEY=${arg%=*}
    VALUE=${arg#*=}
     
    case "$KEY" in
      status)
        STATUS="$VALUE"
        ;;
      database)
        DATABASE="$VALUE"
        ;;
      instance)
        INSTANCE="$VALUE"
        ;;
    esac
     
  fi
done
 
# If database, status and instance values are not set, then exit
# status must be up
if [[ -z "$DATABASE" || -z "$INSTANCE" || "$STATUS" != "up" ]]; then
  exit 0
fi
 
echo "`date`" >> "$LOGFILE"
echo "[$DATABASE][`hostname`] Instance $INSTANCE up" >> "$LOGFILE"
 
#
# Read database software home directory from clusterware
#
DBCONFIG=`$CRS_HOME/bin/crsctl status res ora.$DATABASE.db -f | grep "ORACLE_HOME="`
if [ -z "$DBCONFIG" ]; then
  exit 0
fi
declare -r "$DBCONFIG"
echo "ORACLE_HOME=$ORACLE_HOME" >> "$LOGFILE"
 
# Array function
in_array() {
    local hay needle=$1
    shift
    for hay; do
        [[ $hay == $needle ]] && return 0
    done
    return 1
}
 
#
# Read information about services
#
for service in `$CRS_HOME/bin/crsctl status res | grep -E "ora\.$DATABASE\.(.+)\.svc" | sed -rne "s/NAME=ora\.$DATABASE\.(.+)\.svc//gip"`; do
  SERVICECONFIG=`$ORACLE_HOME/bin/srvctl config service -d $DATABASE -s $service`
  echo "Service $service" >> "$LOGFILE"
  if [[ `echo "$SERVICECONFIG" | grep "Service is enabled" | wc -l` -eq 1 ]]; then
    echo " enabled" >> "$LOGFILE"
    PREFERRED=( `echo "$SERVICECONFIG" | grep "Preferred instances:" | sed -rne "s/.*\: ([a-zA-Z0-9]+)//p" | tr "," "\n"` )
    #
    # Check if current instance is preferred for this service
    #
    if in_array "$INSTANCE" "${PREFERRED[@]}" ; then
      echo " preferred" >> "$LOGFILE"
      #
      # Check if service is already running on current instance
      #
      SRVSTATUS=`$ORACLE_HOME/bin/srvctl status service -d $DATABASE -s $service`
      if [[ "$SRVSTATUS" == *"is not running"* ]]; then
          #
          # if service is not running, then start it
          #
        echo " service stopped, starting" >> "$LOGFILE"
        $ORACLE_HOME/bin/srvctl start service -d "$DATABASE" -s "$service" >> "$LOGFILE"
      else
        #
        # Service is running, but is it running on preferred instance?
        #
        RUNNING=( `echo "$SRVSTATUS" | sed -rne "s/.* ([a-zA-Z0-9]+)//p" | tr "," "\n"` )
        echo "${RUNNING[@]} = ${PREFERRED[@]}"
        if ! in_array "$INSTANCE" "${RUNNING[@]}" ; then
          echo " not running on preferred $INSTANCE" >> "$LOGFILE"
          #
          # Find the first non-preferred running instance
          #
          CURRENT=""
          for inst in "${RUNNING[@]}"; do
            if ! in_array "$inst" "${PREFERRED[@]}" ; then
              CURRENT="$inst"
              break
            fi
          done
          #
          # Relocate
          #
          if [[ -n "$CURRENT" ]]; then
            echo " relocate $CURRENT -> $INSTANCE" >> "$LOGFILE"
            $ORACLE_HOME/bin/srvctl relocate service -d "$DATABASE" -s "$service" -i "$CURRENT" -t "$INSTANCE" >> "$LOGFILE"
          fi
        else
          #
          # Service is already running on preferred instance, no need to do anything
          #
          echo " running on preferred $INSTANCE" >> "$LOGFILE"
        fi
      fi
    fi
  fi
done
 

 

 

Comment

*

沪ICP备14014813号-2

沪公网安备 31010802001379号