Wenn man eine Oracle Datenbank nicht als „RAC“- oder „RAC One Node“-Datenbank in einem Oracle Cluster betreiben möchte, dann ist es möglich, diese als reguläre Cluster Ressource anzulegen, um z.B. ein automatisiertes Failover auf einen anderen Knoten zu realisieren (Singe Instance Failover Cluster).
Hinweis: Es ist ein neuer Artikel veröffentlicht, der den Aufbau einer Single Instance Failover Cluster mit der Grid Infrastructure 19c zum Thema hat und eine aktuelles Version des Action_Scripts bereitstellt:
//frankgerasch.de/2019/05/oracle-se2-im-cluster-es-geht-auch-ohne-rac/
Das Anlegen als Cluster Resource bedeutet, dass die Datenbankinstanz sich nicht, wie sonst bei einer RAC Implementierung üblich, via SRVCTL steuern und verwalten lässt, sondern dass man dafür CRSCTL als Tool nutzen muss. Des Weiteren ist es notwendig ein sogenanntes Action-Script bereitzustellen, welches beim Erstellen der Cluster Ressource als Attribut angegeben wird
Beispiel:
crsctl add resource orcl.inst -type cluster_resource -attr "ACTION_SCRIPT=/u01/app/oracle/admin/ocrl/action_script/action.sh, ...
Das Action-Script muss über die Funktionen „Start“, „Stop“, „Clean“ und „Check“ verfügen und einen Rückgabewert liefern, der die Information liefert, ob die jeweilige Funktion erfolgreich war oder, im Falle der Funktion „Check“, ob die Ressource verfügbar/online ist. Das Action-Script wird von dem Oracle Scriptagent des Cluster Ready Services (CRS) ausgeführt, welcher den Rückgabewert der ausgeführten Aktion prüft und Status an die Clusterware meldet.
Protokolliert werden die Aktionen des Scriptagents in einem eigenen Logfile:
$DIAG/crs/<hostname>/crs/trace/crsd_scriptagent_oracle.trc
Nutzt man für die Client-Verbindungen SCAN-Listener, so ist es erforderlich, dass der Connect-String des Instanzparameter LOCAL_LISTENER die VIP des Servers erhält, auf dem die Instanz gerade gestartet wird. Diese Parameteränderung kann und sollte man ebenfalls in der Startfunktion implementieren.
Beispiel eines Action-Script für eine Oracle Datenbank-Instanz:
#!/bin/sh
export ORACLE_HOME=/u01/app/oracle/product/12.1.0.2/dbhome_2
export GRID_HOME=/u01/app/12.1.0.2/grid
export ORACLE_SID=orcl
check_dbstatus() {
OUTPUT=`$ORACLE_HOME/bin/sqlplus -s / as sysdba << EOF
set echo off define off heading off pagesize 0
SET LINESIZE 100
COLUMN l_output FORMAT A100
SELECT i.status || ' ' || pa.value || '/' || 'ora_' || p.spid || '.aud' AS l_output
FROM v\$session s,
v\$process p,
v\$parameter pa,
v\$instance i
WHERE pa.name = 'audit_file_dest'
AND s.paddr = p.addr
AND s.sid = (select sid from v\$mystat where rownum=1) and s.audsid = sys_context('userenv','sessionid');
exit
EOF`
DBSTATUS=$(echo $OUTPUT | awk '{print $1}')
AUDITFILE=$(echo $OUTPUT | awk '{print $2}')
rm -f $AUDITFILE 2>/dev/null
if [ "$DBSTATUS" == "OPEN" ]
then
return 0
else
return 1
fi
}
case $1 in
'start')
NODE_NAME=$(${GRID_HOME}/bin/olsnodes -l)
VIP_IP=$(${GRID_HOME}/bin/srvctl config vip -n $NODE_NAME | grep "VIP IPv4 Address" | awk '{print $4}')
$ORACLE_HOME/bin/sqlplus -s / as sysdba << EOF
startup
alter system set local_listener='(DESCRIPTION=(ADDRESS_LIST=(ADDRESS=(PROTOCOL=TCP)(HOST=${VIP_IP})(PORT=1521))))' scope=memory;
EOF
check_dbstatus
RET=$?
;;
'stop')
$ORACLE_HOME/bin/sqlplus -s / as sysdba << EOF
shutdown immediate
EOF
NUM=`ps -ef | grep -i smon_${ORACLE_SID} | grep -v grep | wc -l`
if [ $NUM = 0 ]; then
RET=1
else
RET=0
fi
;;
'clean')
$ORACLE_HOME/bin/sqlplus -s / as sysdba << EOF
shutdown abort
EOF
##for i in `ps -ef | grep -i mon_${ORACLE_SID} | awk '{print $2}' ` ;do kill -9 $i; done
NUM=`ps -ef | grep -i smon_${ORACLE_SID} | grep -v grep | wc -l`
if [ $NUM = 0 ]; then
RET=1
else
RET=0
fi
;;
'check')
check_dbstatus
;;
esac