对于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