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