Replicación de Oracle y conmutación por error de conexión rápida UCP



A veces, la configuración de la aplicación Java contiene la dirección IP "principal" del servidor de la base de datos, que puede cambiar, por ejemplo, en los siguientes casos:



  • Cambio controlado de roles de base de datos. "Principal" se convierte en "En espera" y viceversa, "En espera" se convierte en "Principal". Este procedimiento generalmente se denomina "Conmutación".
  • Cambio de emergencia de la función "En espera" a "Principal". Esto se conoce comúnmente como "Conmutación por error".


En ambos casos, la aplicación no solo debe "conocer" la dirección IP del nuevo servidor "Principal", sino que también debe poder acceder a él cuando sea necesario. La siguiente es una guía rápida sobre cómo hacer esto usando Oracle Universal Connection Pool (UCP), así como una demostración de "Switchover".



Para el experimento usaremos:



  • MacBook con 16 GB de RAM (se requieren más de 8 GB para el experimento)
  • Virtual Box versión 6.1.12
  • 2x máquinas virtuales (en adelante VM) con  CentOS 7 Minimal , cada una de las cuales tiene

    • 2x vCPU
    • 2048 GB de RAM (hasta 8 GB temporalmente, uno a la vez)
    • Disco duro de 40 GB
    • audio desactivado para evitar el 100% de la carga de la CPU
  • Base de datos Oracle 19c


Sigamos estos pasos:



  1. Configurar máquinas virtuales
  2. Instalación de Oracle
  3. Replicación de Oracle
  4. Instalación y configuración de Oracle Grid
  5. "Switchover" Java








Creamos máquinas virtuales (en lo sucesivo denominadas VM) con el tipo Linux Red Hat, start. Cuando se inicia Virtual Box, le solicita que seleccione la iso desde la que iniciar la VM (en el experimento, se usa CentOS-7-x86_64-Minimal-1908.iso). Deje todo por defecto, reinicie, actualice, instale "Virtual Box Guest Additions", apague firewalld para que no se interponga. "Todo el mundo sabe cómo se borra el pulido", por lo que solo notamos que después de actualizar las VM, cambiamos sus interfaces de red del adaptador NAT al "adaptador de host virtual" vboxnet0. Para este adaptador, que se puede crear en las herramientas de Virtual Box, configure manualmente la dirección 192.168.56.1/24 y desactive DHCP. Básicamente, es la dirección IP de la puerta de enlace predeterminada para las máquinas virtuales y la dirección de la aplicación Java. Solo por claridad. Y si aún necesita Internet en CentOS,entonces puedes habilitar NAT en macOS:



  1. Cambie al usuario root usando el comando 'sudo su -'.
  2. Permita la redirección del tráfico mediante el comando 'sysctl -w net.inet.ip.forwarding = 1'.
  3. Agregue el contenido del archivo /etc/pf.conf al archivo /var/root/pfnat.conf, en el que en lugar de la línea 3 insertamos la regla para NAT:

    nat en enX desde vboxnet0: red a cualquier -> (enX)


    donde enX es el nombre de la interfaz de red con la ruta predeterminada.
  4. Ejecute el comando 'pfctl -f pfnat.conf -e' para actualizar las reglas de filtrado de paquetes.


Los pasos 2 a 4 se pueden realizar con un solo comando.
sysctl -w net.inet.ip.forwarding=1 \
 && grep -v -E -e '^#.*' -e '^$' /etc/pf.conf | head -n2 > pfnat.conf \
 && INET_PORT=$(netstat -nrf inet | grep default | tr -s ' ' | cut -d ' ' -f 4) \
 && echo "nat on ${INET_PORT} from vboxnet0:network to any -> (${INET_PORT})" >> pfnat.conf \
 && grep -v -E -e '^#.*' -e '^$' /etc/pf.conf | tail -n+3 >> pfnat.conf \
 && pfctl -f pfnat.conf -e




Agregue entradas uniformes a / etc / hosts de todas las VM para que puedan "hacer ping" entre sí por nombres de dominio.



127.0.0.1   localhost localhost.localdomain localhost4 localhost4.localdomain4
::1         localhost localhost.localdomain localhost6 localhost6.localdomain6

192.168.56.78 oracle1.localdomain oracle1
192.168.56.79 oracle2.localdomain oracle2




Instalación de Oracle





Realizamos la instalación "Sólo software" en oracle1 y oracle2  usando paquetes rpm , el directorio con el que se puede compartir desde MacOS a través de Virtual Box (Máquina-> Configuración-> Carpeta Compartida).



yum -y localinstall oracle-database-preinstall-19c-1.0-1.el7.x86_64.rpm


yum -y localinstall oracle-database-ee-19c-1.0-1.x86_64.rpm


A continuación, creamos una instancia de DBMS en la VM "oracle1". Para hacer esto, ejecute el script correspondiente bajo el usuario oralce.



/etc/init.d/oracledb_ORCLCDB-19c configure


Este procedimiento lleva algo de tiempo. Después de crear una instancia en ambos hosts, agregue estas líneas al archivo /home/oracle/.bash_profile:



export ORACLE_HOME="/opt/oracle/product/19c/dbhome_1"
export ORACLE_BASE="/opt/oracle"
export ORACLE_SID="ORCLCDB"
export PATH=$PATH:$ORACLE_HOME/bin


Bueno, también configuramos ssh para mayor comodidad, de modo que pueda conectarse inmediatamente como usuario de Oracle. Nos conectamos al host a través de ssh y nos conectamos a la base de datos bajo el usuario de Oracle.



user@macbook:~$ ssh oracle@oracle1
Last login: Wed Aug 12 16:17:05 2020
[oracle@oracle1 ~]$ sqlplus / as sysdba

SQL*Plus: Release 19.0.0.0.0 - Production on Wed Aug 12 16:19:44 2020
Version 19.3.0.0.0

Copyright (c) 1982, 2019, Oracle.  All rights reserved.


Connected to:
Oracle Database 19c Enterprise Edition Release 19.0.0.0.0 - Production
Version 19.3.0.0.0

SQL>


De hecho, Oracle. Para el experimento, también necesitamos configurar la replicación.



Replicación de Oracle.







Para configurar la replicación, usaremos una instrucción ligeramente actualizada :



  1. Transferimos la base de datos en el servidor oracle1 a "Modo de archivo". Para hacer esto, ejecute los comandos en sqlplus:



    SHUTDOWN IMMEDIATE;


    STARTUP MOUNT;


    ALTER DATABASE ARCHIVELOG;


    ALTER DATABASE OPEN;
  2. Sin salir de sqlplus, habilite "Forzar registro" en el servidor oracle1.



    ALTER DATABASE FORCE LOGGING;


    ALTER SYSTEM SWITCH LOGFILE;
  3. Cree archivos de "registro de rehacer" en el servidor oracle1.

    ALTER DATABASE
          ADD STANDBY LOGFILE
          THREAD 1 GROUP 10 ('/opt/oracle/oradata/ORCLCDB/standby_redo01.log')
          SIZE 209715200;


    ALTER DATABASE
          ADD STANDBY LOGFILE
          THREAD 1 GROUP 11 ('/opt/oracle/oradata/ORCLCDB/standby_redo02.log')
          SIZE 209715200;


    ALTER DATABASE
          ADD STANDBY LOGFILE
          THREAD 1 GROUP 12 ('/opt/oracle/oradata/ORCLCDB/standby_redo03.log')
          SIZE 209715200;


    ALTER DATABASE
          ADD STANDBY LOGFILE
          THREAD 1 GROUP 13 ('/opt/oracle/oradata/ORCLCDB/standby_redo04.log')
          SIZE 209715200;
  4. Active "FLASHBACK" en el servidor oracle1, no funcionará sin él.

    SQL> host

    [oracle @ oracle1 ~] $ mkdir / opt / oracle / recovery_area

    [oracle @ oracle1 ~] $ exit

    SQL> modificar el conjunto del sistema db_recovery_file_dest_size = 2g scope = both;

    SQL> modificar el conjunto del sistema db_recovery_file_dest = '/ opt / oracle / recovery_area' scope = both;

    SQL> ALTER DATABASE FLASHBACK ON;
  5. Habilitamos algo automático en el servidor oracle1.

    SQL> ALTER SYSTEM SET STANDBY_FILE_MANAGEMENT=AUTO;
  6. tnsnames.ora listener.ora oracle1 oracle2 :

    oracle1, $ORACLE_HOME/network/admin/tnsnames.ora
    
    LISTENER_ORCLCDB =
      (ADDRESS = (PROTOCOL = TCP)(HOST = oracle1.localdomain)(PORT = 1521))
    
    ORCLCDB =
      (DESCRIPTION =
        (ADDRESS_LIST =
          (ADDRESS = (PROTOCOL = TCP)(HOST = oracle1.localdomain)(PORT = 1521))
        )
        (CONNECT_DATA =
          (SID = ORCLCDB)
        )
      )
    
    ORCLCDB_STBY =
      (DESCRIPTION =
        (ADDRESS_LIST =
          (ADDRESS = (PROTOCOL = TCP)(HOST = oracle2.localdomain)(PORT = 1521))
        )
        (CONNECT_DATA =
          (SID = ORCLCDB)
        )
      )
    




    oracle1, $ORACLE_HOME/network/admin/listener.ora
    
    LISTENER =
      (DESCRIPTION_LIST =
        (DESCRIPTION =
          (ADDRESS = (PROTOCOL = TCP)(HOST = oracle1.localdomain)(PORT = 1521))
          (ADDRESS = (PROTOCOL = IPC)(KEY = EXTPROC1521))
        )
      )
    
    SID_LIST_LISTENER =
      (SID_LIST =
        (SID_DESC =
          (GLOBAL_DBNAME = ORCLCDB_DGMGRL)
          (ORACLE_HOME = /opt/oracle/product/19c/dbhome_1)
          (SID_NAME = ORCLCDB)
        )
      )
    
    ADR_BASE_LISTENER = /opt/oracle
    




    oracle2, $ORACLE_HOME/network/admin/tnsnames.ora
    
    LISTENER_ORCLCDB =
      (ADDRESS = (PROTOCOL = TCP)(HOST = oracle2.localdomain)(PORT = 1521))
    
    ORCLCDB =
      (DESCRIPTION =
        (ADDRESS_LIST =
          (ADDRESS = (PROTOCOL = TCP)(HOST = oracle1.localdomain)(PORT = 1521))
        )
        (CONNECT_DATA =
          (SID = ORCLCDB)
        )
      )
    
    ORCLCDB_STBY =
      (DESCRIPTION =
        (ADDRESS_LIST =
          (ADDRESS = (PROTOCOL = TCP)(HOST = oracle2.localdomain)(PORT = 1521))
        )
        (CONNECT_DATA =
          (SID = ORCLCDB)
        )
      )
    




    oracle2, $ORACLE_HOME/network/admin/listener.ora
    
    LISTENER =
      (DESCRIPTION_LIST =
        (DESCRIPTION =
          (ADDRESS = (PROTOCOL = TCP)(HOST = oracle2.localdomain)(PORT = 1521))
          (ADDRESS = (PROTOCOL = IPC)(KEY = EXTPROC1521))
        )
      )
    
    SID_LIST_LISTENER =
      (SID_LIST =
        (SID_DESC =
          (GLOBAL_DBNAME = ORCLCDB_STBY_DGMGRL)
          (ORACLE_HOME = /opt/oracle/product/19c/dbhome_1)
          (SID_NAME = ORCLCDB)
        )
      )
    
    ADR_BASE_LISTENER = /opt/oracle
    


  7. oracle1 listener-.

    [oracle@oracle1 ~]$ lsnrctl reload


    [oracle@oracle1 ~]$ lsnrctl status



    LSNRCTL for Linux: Version 19.0.0.0.0 — Production on 15-AUG-2020 08:17:24



    Copyright © 1991, 2019, Oracle. All rights reserved.



    Connecting to (DESCRIPTION=(ADDRESS=(PROTOCOL=TCP)(HOST=oracle1.localdomain)(PORT=1521)))

    STATUS of the LISTENER

    — Alias LISTENER

    Version TNSLSNR for Linux: Version 19.0.0.0.0 — Production

    Start Date 15-AUG-2020 08:09:57

    Uptime 0 days 0 hr. 7 min. 26 sec

    Trace Level off

    Security ON: Local OS Authentication

    SNMP OFF

    Listener Parameter File /opt/oracle/product/19c/dbhome_1/network/admin/listener.ora

    Listener Log File /opt/oracle/diag/tnslsnr/oracle1/listener/alert/log.xml

    Listening Endpoints Summary…

    (DESCRIPTION=(ADDRESS=(PROTOCOL=tcp)(HOST=oracle1.localdomain)(PORT=1521)))

    (DESCRIPTION=(ADDRESS=(PROTOCOL=ipc)(KEY=EXTPROC1521)))

    (DESCRIPTION=(ADDRESS=(PROTOCOL=tcps)(HOST=oracle1.localdomain)(PORT=5500))(Security=(my_wallet_directory=/opt/oracle/admin/ORCLCDB/xdb_wallet))(Presentation=HTTP)(Session=RAW))

    Services Summary…

    Service «ORCLCDB» has 1 instance(s).

    Instance «ORCLCDB», status READY, has 1 handler(s) for this service…

    Service «ORCLCDBXDB» has 1 instance(s).

    Instance «ORCLCDB», status READY, has 1 handler(s) for this service…

    Service «ac8d8d741e3e2a52e0534e38a8c0602d» has 1 instance(s).

    Instance «ORCLCDB», status READY, has 1 handler(s) for this service…

    Service «orclpdb1» has 1 instance(s).

    Instance «ORCLCDB», status READY, has 1 handler(s) for this service…

    The command completed successfully


    ( Data Guard: ORCLCDB_DGMGRL)
    [oracle@oracle1 ~]$ lsnrctl status



    LSNRCTL for Linux: Version 19.0.0.0.0 — Production on 15-AUG-2020 08:17:32



    Copyright © 1991, 2019, Oracle. All rights reserved.



    Connecting to (DESCRIPTION=(ADDRESS=(PROTOCOL=TCP)(HOST=oracle1.localdomain)(PORT=1521)))

    STATUS of the LISTENER

    — Alias LISTENER

    Version TNSLSNR for Linux: Version 19.0.0.0.0 — Production

    Start Date 15-AUG-2020 08:09:57

    Uptime 0 days 0 hr. 7 min. 34 sec

    Trace Level off

    Security ON: Local OS Authentication

    SNMP OFF

    Listener Parameter File /opt/oracle/product/19c/dbhome_1/network/admin/listener.ora

    Listener Log File /opt/oracle/diag/tnslsnr/oracle1/listener/alert/log.xml

    Listening Endpoints Summary…

    (DESCRIPTION=(ADDRESS=(PROTOCOL=tcp)(HOST=oracle1.localdomain)(PORT=1521)))

    (DESCRIPTION=(ADDRESS=(PROTOCOL=ipc)(KEY=EXTPROC1521)))

    (DESCRIPTION=(ADDRESS=(PROTOCOL=tcps)(HOST=oracle1.localdomain)(PORT=5500))(Security=(my_wallet_directory=/opt/oracle/admin/ORCLCDB/xdb_wallet))(Presentation=HTTP)(Session=RAW))

    Services Summary…

    Service «ORCLCDB» has 1 instance(s).

    Instance «ORCLCDB», status READY, has 1 handler(s) for this service…

    Service «ORCLCDBXDB» has 1 instance(s).

    Instance «ORCLCDB», status READY, has 1 handler(s) for this service…

    Service «ORCLCDB_DGMGRL» has 1 instance(s).

    Instance «ORCLCDB», status UNKNOWN, has 1 handler(s) for this service…

    Service «ac8d8d741e3e2a52e0534e38a8c0602d» has 1 instance(s).

    Instance «ORCLCDB», status READY, has 1 handler(s) for this service…

    Service «orclpdb1» has 1 instance(s).

    Instance «ORCLCDB», status READY, has 1 handler(s) for this service…

    The command completed successfully
  8. SYS oracle1.

    SQL> alter user sys identified by "pa_SSw0rd";
  9. oracle2 listener .

    [oracle@oracle2 ~]$ lsnrctl start

    [oracle@oracle2 ~]$ orapwd file=$ORACLE_BASE/product/19c/dbhome_1/dbs/orapwORCLCDB entries=10 password=pa_SSw0rd

    [oracle@oracle2 ~]$ echo "*.db_name='ORCLCDB'" > /tmp/initORCLCDB_STBY.ora

    [oracle@oracle2 ~]$ mkdir -p $ORACLE_BASE/oradata/ORCLCDB/pdbseed

    [oracle@oracle2 ~]$ mkdir -p $ORACLE_BASE/oradata/ORCLCDB/ORCLPDB1

    [oracle@oracle2 ~]$ mkdir -p $ORACLE_BASE/admin/ORCLCDB/adump

    [oracle@oracle2 ~]$ mkdir /opt/oracle/recovery_area

    [oracle@oracle2 ~]$ sqlplus / as sysdba

    SQL> STARTUP NOMOUNT PFILE='/tmp/initORCLCDB_STBY.ora'

    [oracle@oracle2 ~]$ rman TARGET sys/pa_SSw0rd@ORCLCDB AUXILIARY sys/pa_SSw0rd@ORCLCDB_STBY

    RMAN> DUPLICAR LA BASE DE DATOS OBJETIVO PARA ESPERA DESDE LA BASE DE DATOS ACTIVA DORECOVER SPFILE SET db_unique_name = 'ORCLCDB_STBY' COMMENT 'Está en espera' NOFILENAMECHECK;
  10. Inicie Data Guard en ambos servidores (oracle1 y oracle2).

    SQL> ALTERAR EL CONJUNTO DEL SISTEMA dg_broker_start = true;
  11. En el servidor oracle1, conéctese a la consola de administración de Data Guard y cree una configuración.

    [oracle @ oracle1 ~] $ dgmgrl sys / pa_SSw0rd @ ORCLCDB

    DGMGRL> CREAR CONFIGURACIÓN my_dg_config COMO LA BASE DE DATOS PRIMARIA ES ORCLCDB EL IDENTIFICADOR DE CONEXIÓN ES ORCLCDB;

    DGMGRL> ADD DATABASE ORCLCDB_STBY COMO IDENTIFICADOR DE CONEXIÓN ES ORCLCDB_STBY MANTENIDO COMO FÍSICO;

    DGMGRL> habilitar configuración;




Entonces, como resultado de crear una réplica y habilitar Data Guard, tenemos el siguiente estado:



DGMGRL> show configuration

Configuration - my_dg_config

  Protection Mode: MaxPerformance
  Members:
  orclcdb      - Primary database
    orclcdb_stby - Physical standby database 
      Warning: ORA-16854: apply lag could not be determined

Fast-Start Failover:  Disabled

Configuration Status:
WARNING   (status updated 40 seconds ago)


Ésta es una mala condición. Esperemos un poco ...



DGMGRL> show configuration

Configuration - my_dg_config

  Protection Mode: MaxPerformance
  Members:
  orclcdb      - Primary database
    orclcdb_stby - Physical standby database 

Fast-Start Failover:  Disabled

Configuration Status:
SUCCESS   (status updated 55 seconds ago)


¡Ahora el estado es bueno! Sin embargo, la réplica es muy pasiva, no acepta solicitudes de lectura (MODO ABIERTO: MONTADO).



SQL> show pdbs

    CON_ID CON_NAME			  OPEN MODE  RESTRICTED
---------- ------------------------------ ---------- ----------
 
	 2 PDB$SEED			  MOUNTED
	 3 ORCLPDB1			  MOUNTED


Activemos la réplica para que acepte solicitudes de lectura. Entonces, en el futuro, podremos descargar el servidor con la base "Primaria". Esto es lo que se llama "Active Data Guard" o espera activa . En el servidor oracle2, ejecute la siguiente secuencia de comandos en sqlplus:

alter database 
      recover managed standby database cancel;


alter database open;


alter database 
      recover managed standby database 
      using current logfile 
      disconnect from session;


alter pluggable database all open;


Ahora puede leer de la réplica (MODO ABIERTO: SÓLO LEER):

SQL> show pdbs;

    CON_ID CON_NAME			  OPEN MODE  RESTRICTED
---------- ------------------------------ ---------- ----------
 
	 2 PDB$SEED			  READ ONLY  NO
	 3 ORCLPDB1			  READ ONLY  NO


Y en la consola de DataGuard en el servidor oracle1, todo se ve bien:

DGMGRL> show configuration;

Configuration - my_dg_config

  Protection Mode: MaxPerformance
  Members:
  orclcdb      - Primary database
    orclcdb_stby - Physical standby database 

Fast-Start Failover:  Disabled

Configuration Status:
SUCCESS   (status updated 19 seconds ago)


A pesar de que ahora tenemos Data Guard Active, el clúster sigue siendo en gran parte pasivo. Todavía no nos dice una palabra a nosotros y a nuestra increíble aplicación Java de que Primary ya no es Primary. Para hacer esto, otro servicio, ONS (Oracle Notification Services), debe estar ejecutándose en los servidores del clúster. Y parece que instalar Oracle Database no es suficiente para ejecutar este servicio, necesitaremos instalar Oracle Grid.







Instalación y configuración de Oracle Grid.







Aquí todo es bastante simple: como en el proceso de instalación de Oracle Database, simplemente seguiremos las instrucciones oficiales .



  1.   oracle1  oracle2 root    Oracle Grid, gcc-c++, oracle   asm.   Virtual Box, Oracle, Oracle Grid    .

    mkdir -p /opt/oracle/product/19c/grid \
            && cp -r /mnt/oracle_grid_19300/LINUX/* /opt/oracle/product/19c/grid/ \
            && chown -R oracle:oinstall /opt/oracle/product/19c/grid


    yum install -y gcc-c++


    groupadd asm && usermod -aG asm oracle


  2. ,   oracle, Oracle Grid.

    cd /opt/oracle/product/19c/grid/ && ./runcluvfy.sh stage -pre hacfg


    Verifying Physical Memory ...FAILED

    Required physical memory = 8GB

    Verifying Swap Size ...FAILED

    Required = 2.6924GB (2823138.0KB); Found = 2GB (2097148.0KB)]



      - ,     swap, Oracle Grid ,   .
  3. oracle2, oracle1.

    SQL> shutdown immediate


    # poweroff
  4. oracle1  8192 ,  VM   swap root.

    dd if=/dev/zero of=/swap_file bs=1G count=7 \
                && chmod 600 /swap_file && mkswap /swap_file \
                && echo '/swap_file  swap  swap  defaults  0 0' >> /etc/fstab \
                && swapoff -a && swapon -a
  5. , , .

    [oracle@oracle1 grid]$ cd /opt/oracle/product/19c/grid/ && ./runcluvfy.sh stage -pre hacfg

    Pre-check for Oracle Restart configuration was successful.


    ! Oracle Grid.
  6. oracle   oracle1  /opt/oracle/product/19c/grid/ grid_configwizard.rsp.

    cd /opt/oracle/product/19c/grid/ && touch grid_configwizard.rsp


    grid_configwizard.rsp , oracle restart, ASM   .

    oracle.install.responseFileVersion=/oracle/install/rspfmt_crsinstall_response_schema_v19.0.0

    INVENTORY_LOCATION=/opt/oracle/oraInventory

    oracle.install.option=CRS_SWONLY

    ORACLE_BASE=/opt/oracle

    oracle.install.asm.OSDBA=oinstall

    oracle.install.asm.OSASM=asm

    oracle.install.asm.SYSASMPassword=oracle

    oracle.install.asm.diskGroup.name=data

    oracle.install.asm.diskGroup.redundancy=NORMAL

    oracle.install.asm.diskGroup.AUSize=4

    oracle.install.asm.diskGroup.disksWithFailureGroupNames=/dev/sdb

  7.   oracle grid   .

    ./gridSetup.sh -silent \
                   -responseFile /opt/oracle/product/19c/grid/grid_configwizard.rsp
  8.   , oracle grid root,   .

    /opt/oracle/product/19c/grid/root.sh
  9. , oracle restart root roothas.sh.

    cd /opt/oracle/product/19c/grid/crs/install/ && ./roothas.sh


  10.   oracle   runInstaller.

    cd /opt/oracle/product/19c/grid/oui/bin/ \
                                && ./runInstaller -updateNodeList \
                                    ORACLE_HOME=/opt/oracle/product/19c/grid \
                                    -defaultHomeName CLUSTER_NODES= CRS=TRUE
  11. oracle1 /etc/fstab , /swap_file, 2048 RAM.
  12. " Oracle Grid" VM oracle2.
  13. ,   ,   Oracle Restart.    oracle1 oracle     Oracle Restart.

    srvctl add database -db ORCLCDB \
                -oraclehome /opt/oracle/product/19c/dbhome_1 \
                -role PRIMARY


    /opt/oracle/product/19c/grid/bin/crsctl modify \
                res ora.cssd -attr "AUTO_START=always" -unsupported


    /opt/oracle/product/19c/grid/bin/crsctl stop has


    /opt/oracle/product/19c/grid/bin/crsctl start has
  14.   oracle2 oracle     Oracle Restart.

    /opt/oracle/product/19c/grid/bin/crsctl modify \
                res ora.cssd -attr "AUTO_START=always" -unsupported


    /opt/oracle/product/19c/grid/bin/crsctl stop has


    /opt/oracle/product/19c/grid/bin/crsctl start has


    srvctl add database -db ORCLCDB_STBY \
               -oraclehome /opt/oracle/product/19c/dbhome_1 \
               -role PHYSICAL_STANDBY \
               -spfile /opt/oracle/product/19c/dbhome_1/dbs/spfileORCLCDB.ora \
               -dbname ORCLCDB -instance ORCLCDB
  15. En ambos servidores, oracle1 y oracle2, bajo el usuario de oracle, agregue un escucha a la configuración de reinicio de Oracle.

    srvctl add listener
  16. En el servidor oracle1, bajo el usuario de oracle, agregue a la configuración e inicie el servicio de base de datos, ORCLCDB.

    srvctl add service -db ORCLCDB -service orclpdb -l PRIMARY -pdb ORCLPDB1


    srvctl start service -db ORCLCDB -service orclpdb
  17. En el servidor de oracle2, bajo el usuario de oracle, agregue el servicio de base de datos, ORCLCDB_STBY a la configuración e inicie la instancia de la base de datos

    srvctl add service -db ORCLCDB_STBY -service orclpdb -l PRIMARY -pdb ORCLPDB1


    srvctl start database -db ORCLCDB_STBY
  18. En el servidor oracle1 y oracle2, inicie el servicio ons.

    srvctl enable ons


    srvctl start ons




Demo "Switchover" en una aplicación de prueba Java







Como resultado, tenemos 2 servidores Oracle con replicación en modo activo-en espera y servicio ons, a los cuales se enviarán eventos de conmutación y la aplicación Java podrá procesar estos eventos a medida que lleguen.



Creemos un usuario de prueba y una tabla en Oracle.
  oracle1 oracle   sqlplus  

  • sqlplus / as sysdba
  • alter session set container=ORCLPDB1;
  • CREATE USER testus 
           IDENTIFIED BY test 
           DEFAULT TABLESPACE USERS 
           QUOTA UNLIMITED ON USERS;
  • GRANT CONNECT, 
          CREATE SESSION, 
          CREATE TABLE 
          TO testus;
  • CREATE TABLE TESTUS.MESSAGES (TIMEDATE TIMESTAMP, MESSAGE VARCHAR2(100));




Después de crear una tabla y un usuario de prueba, nos conectamos al servidor oracle2 y "abrimos" la instancia para lectura para asegurarnos de que la replicación está funcionando.

 
 [oracle@oracle2 ~]$ sqlplus / as sysdba
 SQL> alter pluggable database all open;
 SQL> alter session set container=ORCLPDB1;
 SQL> column table_name format A10;
 SQL> column owner format A10;
 SQL> select table_name, owner from dba_tables where owner like '%TEST%';

TABLE_NAME OWNER
---------- ----------
MESSAGES   TESTUS


La aplicación de prueba consta de una sola clase Main, en un bucle intenta agregar un registro a la tabla de prueba y luego leer el mismo registro (ver los métodos "putNewMessage ()" y "getLastMessage ()"). También existe el método "getConnectionHost ()", que a partir del objeto "conexión" utilizando la "API Reflection" obtiene la dirección IP de la conexión a la base de datos. Como puede ver en la consola, después del "cambio", esta dirección cambia.



Inicie la aplicación de prueba y ejecute el "cambio" en la consola de Data Guard.



DGMGRL> switchover to orclcdb_stby;


Vemos como cambia la dirección IP de la conexión en el log de la aplicación, el tiempo de inactividad es de 1 minuto:



[Wed Aug 26 23:56:55 MSK 2020]: Host 192.168.56.78: - 2020-08-26 23:56:55|  ?
[Wed Aug 26 23:56:56 MSK 2020]: Host 192.168.56.78: - 2020-08-26 23:56:56|  ?
[Wed Aug 26 23:56:57 MSK 2020]: Host 192.168.56.78: - 2020-08-26 23:56:57|  ?
[Wed Aug 26 23:56:58 MSK 2020]: SQLException: -  !
[Wed Aug 26 23:57:02 MSK 2020]: SQLException: -  !
[Wed Aug 26 23:57:06 MSK 2020]: SQLException: -  !
[Wed Aug 26 23:57:10 MSK 2020]: SQLException: -  !
[Wed Aug 26 23:57:14 MSK 2020]: SQLException: -  !
[Wed Aug 26 23:57:18 MSK 2020]: SQLException: -  !
[Wed Aug 26 23:57:23 MSK 2020]: SQLException: -  !
[Wed Aug 26 23:57:27 MSK 2020]: SQLException: -  !
[Wed Aug 26 23:57:31 MSK 2020]: SQLException: -  !
[Wed Aug 26 23:57:35 MSK 2020]: SQLException: -  !
[Wed Aug 26 23:57:39 MSK 2020]: SQLException: -  !
[Wed Aug 26 23:57:43 MSK 2020]: SQLException: -  !
[Wed Aug 26 23:57:47 MSK 2020]: SQLException: -  !
[Wed Aug 26 23:57:51 MSK 2020]: Host 192.168.56.79: - 2020-08-26 23:57:52|  ?
[Wed Aug 26 23:57:53 MSK 2020]: Host 192.168.56.79: - 2020-08-26 23:57:53|  ?
[Wed Aug 26 23:57:54 MSK 2020]: Host 192.168.56.79: - 2020-08-26 23:57:54|  ?


Regrese para estar seguro.



DGMGRL> switchover to orclcdb;


La situación es simétrica.



[Wed Aug 26 23:58:54 MSK 2020]: Host 192.168.56.79: - 2020-08-26 23:58:54|  ?
[Wed Aug 26 23:58:55 MSK 2020]: Host 192.168.56.79: - 2020-08-26 23:58:55|  ?
[Wed Aug 26 23:58:56 MSK 2020]: SQLException: -  !
[Wed Aug 26 23:59:00 MSK 2020]: SQLException: -  !
[Wed Aug 26 23:59:04 MSK 2020]: SQLException: -  !
[Wed Aug 26 23:59:08 MSK 2020]: SQLException: -  !
[Wed Aug 26 23:59:12 MSK 2020]: SQLException: -  !
[Wed Aug 26 23:59:16 MSK 2020]: SQLException: -  !
[Wed Aug 26 23:59:20 MSK 2020]: SQLException: -  !
[Wed Aug 26 23:59:24 MSK 2020]: SQLException: -  !
[Wed Aug 26 23:59:28 MSK 2020]: SQLException: -  !
[Wed Aug 26 23:59:32 MSK 2020]: SQLException: -  !
[Wed Aug 26 23:59:36 MSK 2020]: SQLException: -  !
[Wed Aug 26 23:59:40 MSK 2020]: SQLException: -  !
[Wed Aug 26 23:59:44 MSK 2020]: Host 192.168.56.78: - 2020-08-26 23:59:45|  ?
[Wed Aug 26 23:59:46 MSK 2020]: Host 192.168.56.78: - 2020-08-26 23:59:46|  ?


Además, prestemos atención a las conexiones TCP en los hosts oralce1 y oracle2. El puerto de datos está ocupado con conexiones solo en el primario, el puerto ONS está ocupado tanto en el primario como en la réplica.



Antes del cambio.

oracle1
Every 1.0s: ss -tapn | grep 192.168.56.1 | grep ESTAB | grep -v ":22"

ESTAB 0 0 192.168.56.78:1521 192.168.56.1:49819 users:(("oracle_21115_or"...))
ESTAB 0 0 192.168.56.78:1521 192.168.56.1:49822 users:(("oracle_21117_or"...))
ESTAB 0 0 [::ffff:192.168.56.78]:6200 [::ffff:192.168.56.1]:49820 users:(("ons"...))



oracle2
Every 1.0s: ss -tapn | grep 192.168.56.1 | grep ESTAB | grep -v ":22"

ESTAB 0 0 [::ffff:192.168.56.79]:6200 [::ffff:192.168.56.1]:49821 users:(("ons"...))


Después del cambio.

oracle1
Every 1.0s: ss -tapn | grep 192.168.56.1 | grep ESTAB | grep -v 22  Wed Aug 26 16:57:57 2020

ESTAB 0 0 [::ffff:192.168.56.78]:6200 [::ffff:192.168.56.1]:51457 users:(("ons"...))



oracle2
Every 1.0s: ss -tapn | grep 192.168.56.1 | grep ESTAB | grep -v ":22" Wed Aug 26 16:58:35 2020

ESTAB 0 0 192.168.56.79:1521 192.168.56.1:52259 users:(("oracle_28212_or"...))
ESTAB 0 0 192.168.56.79:1521 192.168.56.1:52257 users:(("oracle_28204_or"...))
ESTAB 0 0 [::ffff:192.168.56.79]:6200 [::ffff:192.168.56.1]:51458 users:(("ons"...))


Conclusión



Por lo tanto, simulamos un clúster de Data Guard en un entorno de laboratorio con un número mínimo de configuraciones e implementamos una conexión de conmutación por error de una aplicación Java de prueba. Ahora sabemos lo que el desarrollador quiere del DBA y el DBA del desarrollador. Queda por lanzar y probar Fast Start Failover, pero, quizás, en el marco de un artículo separado.



All Articles