[Java, Oracle] Репликация Oracle и UCP Fast Connection Failover

Автор Сообщение
news_bot ®

Стаж: 6 лет 9 месяцев
Сообщений: 27286

Создавать темы news_bot ® написал(а)
12-Сен-2020 19:30

Иногда в конфигурации Java-приложения есть IP-адрес "Primary" сервера базы данных, который может поменяться, например, в следующих случаях:
  • Контролируемая смена ролей баз данных. "Primary" становится "Standby" и наоборот, "Standby" становится "Primary". Такая процедура обычно называется "Switchover".
  • Аварийная смена роли "Standby" на "Primary". Это обычно называется "Failover".

В обоих случаях приложение должно не только "знать" про IP-адрес нового "Primary" сервера, но и уметь к нему обратиться тогда, когда это нужно. Далее следует краткая инструкция того, как это можно сделать с помощью Oracle Universal Connection Pool (UCP), а также демонстрация "Switchover".
Для эксперимента будем использовать:
  • MacBook c объемом RAM 16 Гб (для эксперимента нужно более 8 Гб)
  • Virtual Box версии 6.1.12
  • 2x виртуальные машины (далее VM) c CentOS 7 Minimal, каждая из которых имеет
    • 2x vCPU
    • 2048 Гб RAM (с временным увеличением до 8Гб, по очереди)
    • 40 Гб HDD
    • отключенное аудио, чтобы избежать загрузки CPU 100%
  • Oracle Database 19c

Выполним следующие шаги:

Настройка виртуальных машин

Создаем виртуальные машины (далее VMs) с типом Linux Red Hat, стартуем. При запуске Virtual Box предлагает выбрать iso, с которого запустить VM (в эксперименте используется CentOS-7-x86_64-Minimal-1908.iso). Оставляем все по умолчанию, перезагружаем, обновляем, устанавливаем "Virtual Box Guest Additions", отключаем firewalld, чтобы не мешался. "Как очищается политура — это всякий знает", поэтому отметим только, что после обновления VMs переключаем их сетевые интерфейсы с адаптера NAT на "виртуальный адаптер хоста" vboxnet0. Этому адаптеру, который можно создать в инструментах Virtual Box, вручную задаем адрес 192.168.56.1/24 и отключаем DHCP. По сути, это IP-адрес шлюза по умолчанию для VMs и адрес Java-приложения. Просто для наглядности. А если на CentOS все еще нужен интернет, то можно включить NAT на MacOS:
  • Переключаемся в пользователя root с помощью команды ’sudo su -′.
  • Разрешаем перенаправление трафика с помощью команды ’sysctl -w net.inet.ip.forwarding=1′.
  • В файл /var/root/pfnat.conf добавляем содержательную часть файла /etc/pf.conf, в которую на место строки № 3 вставляем правило для NAT:
    nat on enX from vboxnet0:network to any -> (enX)

    где enX — имя сетевого интерфейса с маршрутом по умолчанию.
  • Выполняем команду ’pfctl -f pfnat.conf -e′, чтобы обновить правила пакетного фильтра.

Шаги 2-4 можно выполнить в одну команду.

SPL
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


В /etc/hosts всех VMs добавляем однообразные записи, чтобы они могли "пинговать" друг друга по доменным именам.
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

Установка Oracle

Выполняем "Software only" установку на oracle1 и oracle2 с помощью rpm-пакетов, директорию с которыми можно расшарить с MacOS через Virtual Box (Machine->Settings->Shared Folder).
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

Далее, выполняем создание экземпляра СУБД на VM "oracle1". Для этого под пользователем oralce запускаем соответствующий скрипт.
/etc/init.d/oracledb_ORCLCDB-19c configure

Эта процедура занимает некоторое время. После создания экземпляра на обоих хостах добавляем в файл /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

Ну и настраиваем ssh для удобства, чтобы можно было сразу подключиться под пользователем oracle. Подключаемся к хосту по ssh и под пользователем 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 © 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>

Собственно, Oracle. Для эксперимента нам также нужно настроить репликацию.
Репликация Oracle.

Для настройки репликации воспользуемся немного дополненной инструкцией:
  • Переводим БД на сервере oracle1 в "Archive Mode". Для этого в sqlplus выполняем команды:
    SHUTDOWN IMMEDIATE;

    STARTUP MOUNT;

    ALTER DATABASE ARCHIVELOG;

    ALTER DATABASE OPEN;
  • Не выходя из sqlplus, включаем "Force logging" на сервере oracle1.
    ALTER DATABASE FORCE LOGGING;

    ALTER SYSTEM SWITCH LOGFILE;
  • Создаем "redo log" файлы на сервере 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;
  • Включаем "FLASHBACK" на сервере oracle1, без него работать не будет.
    SQL> host
    [oracle@oracle1 ~]$ mkdir /opt/oracle/recovery_area
    [oracle@oracle1 ~]$ exit
    SQL> alter system set db_recovery_file_dest_size=2g scope=both;
    SQL> alter system set db_recovery_file_dest='/opt/oracle/recovery_area' scope=both;
    SQL> ALTER DATABASE FLASHBACK ON;
  • Включаем нечто автоматическое на сервере oracle1.
    SQL> ALTER SYSTEM SET STANDBY_FILE_MANAGEMENT=AUTO;
  • Модифицируем tnsnames.ora и listener.ora на сервере oracle1 и oracle2 до следующих содержаний:

    oracle1, файл $ORACLE_HOME/network/admin/tnsnames.ora

    SPL
    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

    SPL
    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

    SPL
    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

    SPL
    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

    • На сервере oracle1 перезагружаем конфигурацию слушателя listener-а.
      [oracle@oracle1 ~]$ lsnrctl reload

      Было

      SPL
      [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)

      SPL
      [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
      • Меняем пароль пользователю SYS на сервере oracle1.
        SQL> alter user sys identified by "pa_SSw0rd";
      • На сервере 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> DUPLICATE TARGET DATABASE FOR STANDBY FROM ACTIVE DATABASE DORECOVER SPFILE SET db_unique_name='ORCLCDB_STBY' COMMENT 'Is standby' NOFILENAMECHECK;
      • На обоих серверах (oracle1 и oracle2) запускаем Data Guard.
        SQL> ALTER SYSTEM SET dg_broker_start=true;
      • На сервере oracle1 подключаемся к консоли управления Data Guard и создаем конфигурацию.
        [oracle@oracle1 ~]$ dgmgrl sys/pa_SSw0rd@ORCLCDB
        DGMGRL> CREATE CONFIGURATION my_dg_config AS PRIMARY DATABASE IS ORCLCDB CONNECT IDENTIFIER IS ORCLCDB;
        DGMGRL> ADD DATABASE ORCLCDB_STBY AS CONNECT IDENTIFIER IS ORCLCDB_STBY MAINTAINED AS PHYSICAL;
        DGMGRL> enable configuration;

      Итак, в результате создания реплики и включения Data Guard мы имеем следующее состояние:
      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)

      Это плохое состояние. Давайте подождем немного…
      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)

      Вот теперь состояние хорошее! Правда, реплика весьма пассивна, она не принимает запросы на чтение (OPEN MODE: MOUNTED).
      SQL> show pdbs
          CON_ID CON_NAME        OPEN MODE  RESTRICTED
      ---------- ------------------------------ ---------- ----------
        2 PDB$SEED        MOUNTED
        3 ORCLPDB1        MOUNTED

      Давайте сделаем реплику активной, чтобы она принимала запросы на чтение. Тогда мы, в перспективе, сможем разгрузить сервер с "Primary" базой. Это то, что называется "Active Data Guard", либо active standby. На сервере oracle2 выполняем следующую последовательность команд в 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;

      Вот теперь можно и почитать с реплики (OPEN MODE: READ ONLY):
      SQL> show pdbs;
          CON_ID CON_NAME        OPEN MODE  RESTRICTED
      ---------- ------------------------------ ---------- ----------
        2 PDB$SEED        READ ONLY  NO
        3 ORCLPDB1        READ ONLY  NO

      И в консоли DataGuard на сервере oracle1 все выглядит неплохо:
      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)

      Несмотря на то, что Data Guard у нас теперь Active, кластер все еще во многом пассивен. Нам и нашему восхитительному Java-приложению он по-прежнему не скажет ни слова о том, что Primary теперь не Primary. Для этого на серверах кластера должна быть запущена еще одна служба, ONS (Oracle Notification Services). И похоже, что для запуска этой службы установки Oracle Database недостаточно, нам потребуется установить Oracle Grid.
      Установка и настройка Oracle Grid.

      Тут все достаточно просто: как и в процессе установки Oracle Database мы просто будем следовать официальной инструкции.
      • На сервере 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

      • Далее, переключаемся в пользователя 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 встал, а потом возвращать прежние значения.
      • Выключаем сперва oracle2, затем oracle1.
        SQL> shutdown immediate

        # poweroff
      • Добавляем оперативной памяти 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
      • Вновь проверяем соответствие машины системным требованиям, чтобы убедиться, что все хорошо.
        [oracle@oracle1 grid]$ cd /opt/oracle/product/19c/grid/ && ./runcluvfy.sh stage -pre hacfg
        Pre-check for Oracle Restart configuration was successful.

        Отлично! Теперь можно выполнить конфигурацию Oracle Grid.
      • Под пользователем 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
      • Выполняем скрипт по настройке oracle grid в консольном режиме.
        ./gridSetup.sh -silent \
                       -responseFile /opt/oracle/product/19c/grid/grid_configwizard.rsp
      • По результатам настройки, oracle grid просит выполнить скрипт под пользователем root, что мы и делаем.
        /opt/oracle/product/19c/grid/root.sh
      • Далее, выполняем настройку oracle restart посредством запуска под пользователем root скрипта roothas.sh.
        cd /opt/oracle/product/19c/grid/crs/install/ && ./roothas.sh

      • Переключаемся в пользователя oracle и выполняем скрипт runInstaller.
        cd /opt/oracle/product/19c/grid/oui/bin/ \
                                    && ./runInstaller -updateNodeList \
                                        ORACLE_HOME=/opt/oracle/product/19c/grid \
                                        -defaultHomeName CLUSTER_NODES= CRS=TRUE
      • На машине oracle1 комментируем в /etc/fstab строчку, которая начинается на /swap_file, выключаем машину и возвращаем ей 2048 Мб RAM.
      • Повторяем все предыдущие шаги раздела "Установка и настройка Oracle Grid" для VM oracle2.
      • После того, как мы снова выдали виртуальным машинам вменяемое количество оперативной памяти, добавляем нужные сервисы в конфигурацию 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
      • На сервере 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
      • На обоих серверах, oracle1 и oracle2, под пользователем oracle добавляем listener в конфигурацию Oracle Restart.
        srvctl add listener
      • На сервере oracle1 под пользователем oracle добавляем в конфигурацию и запускаем сервис БД, ORCLCDB.
        srvctl add service -db ORCLCDB -service orclpdb -l PRIMARY -pdb ORCLPDB1

        srvctl start service -db ORCLCDB -service orclpdb
      • На сервере oracle2 под пользователем oracle добавляем в конфигурацию сервис БД, ORCLCDB_STBY, и стартуем экземпляр БД
        srvctl add service -db ORCLCDB_STBY -service orclpdb -l PRIMARY -pdb ORCLPDB1

        srvctl start database -db ORCLCDB_STBY
      • На сервере oracle1 и oracle2 запустим службу ons.
        srvctl enable ons

        srvctl start ons

      Демонстрация "Switchover" на тестовом Java приложении

      В итоге мы имеем 2 сервера oracle с репликацией в режиме active-standby и службой ons, в которую будут отправляться события о переключениях, и Java-приложение сможет обрабатывать эти события по мере их поступления.

      Создаем тестового пользователя и таблицу в Oracle.

      SPL
      Подключаемся к серверу 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));


      После создания тестового пользователя и таблицы, подключаемся к серверу oracle2 и "открываем" экземпляр на чтение, чтобы убедиться, что репликация работает.
      [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

      Тестовое приложение состоит из одного только класса Main, в цикле пытается добавить запись в тестовую таблицу, а затем эту же запись прочитать (см. методы "putNewMessage()" и "getLastMessage()"). Еще имеется метод "getConnectionHost()", который из объекта "connection" с помощью "Reflection API" получает IP-адрес подключения к БД. Как далее видно в консоли, после "switchover" этот адрес меняется.
      Запускаем тестовое приложение и выполняем в консоли Data Guard "switchover".
      DGMGRL> switchover to orclcdb_stby;

      Видим, как в логе приложения меняется IP-адрес подключения, простой составляет 1 минуту:
      [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|Ты кто такой?

      Переключаем обратно, для верности.
      DGMGRL> switchover to orclcdb;

      Ситуация симметричная.
      [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|Ты кто такой?

      Также, обратим внимание на TCP-соединения на хостах oralce1 и oracle2. Data-порт занят подключениями только на primary, ONS-порт занят и на primary, и на replica.

      До switchover.

      SPL
      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"...))

      После switchover.

      SPL
      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"...))

      Заключение
      Таким образом, мы смоделировали в лабораторных условиях кластер Data Guard с минимальным количеством настроек и реализовали отказоустойчивое подключение тестового Java-приложения. Теперь мы знаем что разработчик хочет от DBA, а DBA от разработчика. Осталось еще запустить и протестировать Fast Start Failover, но, пожалуй, в рамках отдельной статьи.
      ===========
      Источник:
      habr.com
      ===========

      Похожие новости: Теги для поиска: #_java, #_oracle, #_oracle_database_19c, #_data_guard, #_oracle_ucp, #_fast_connection_failover, #_oracle_notification_service, #_ons, #_java, #_oracle
Профиль  ЛС 
Показать сообщения:     

Вы не можете начинать темы
Вы не можете отвечать на сообщения
Вы не можете редактировать свои сообщения
Вы не можете удалять свои сообщения
Вы не можете голосовать в опросах
Вы не можете прикреплять файлы к сообщениям
Вы не можете скачивать файлы

Текущее время: 22-Ноя 18:21
Часовой пояс: UTC + 5