Page tree

Versions Compared

Key

  • This line was added.
  • This line was removed.
  • Formatting was changed.
Comment: В "Контроль невалидных объектов" добавила примечание о пакетах с префиксом MI_

Table of Contents


Info

This article is in English Working with the DB Dumps

Для работы с дампами БД следует пользоваться специальным скриптом dump.sh, который располагается, как правило, в директории /opt/hydra/oracle/scripts. Скрипт обязательно следует вызвать под пользователем oracle с инициализированным окружением. Инициализировать окружение для пользователя oracle с помощью sudo можно выполнить следующим образом:

...

languagebash

...

устанавливается при помощи deb пакета hydra-utils. Этот пакет совместим с операционными системами Debian 9 и ниже. Для операционной системы Oracle Linux необходимо использовать отдельный Docker-контейнер.

У скрипта для работы с дампами БД существуют следующие варианты запуска:

  • export — снятие дампа. Дамп снимается в директорию для дампов, установленную в БД (как правило, это /var/oradata/dumps).
  • drop — очистка. Перед очисткой следует обязательно убедиться, что БД не является промышленной.
  • import — загрузка дампа в БД. Перед загрузкой дампа обязательно следует выполнить очистку. Дамп поднимается из директории для дампов, установленной в БД (как правило, это /var/oradata/dumps). После импортирования флаг «Признак промышленной базы данных» сбрасывается.

...

  • -i — название БД
  • -o — название схемы
  • -p — пароль пользователя AIS_NET
  • -f — название дампа (файла с дампом)
  • -s — отказ от предупреждающего сообщения при очистке БД

Пример использования dump.sh при нативной установке hydra-utils

При установке hydra-utils скрипт снятия дампов устанавливаются в следующую директорию -  /opt/hydra/oracle/scripts. Скрипт обязательно следует вызвать под пользователем oracle с инициализированным окружением. Инициализировать окружение для пользователя oracle с помощью sudo можно выполнить следующим образом:

Code Block
languagebash
sudo -u oracle -i

Пример вызова скрипта для переноса дампа БД с hydra на hydra2:

  1. Снятие дампа с hydra:

    Code Block
    languagebash
    /opt/hydra/oracle/scripts/dump.sh -i hydra -p password -f hydra_dump export
    


  2. Очистка hydra2:

    Code Block
    languagebash
    /opt/hydra/oracle/scripts/dump.sh -i hydra2 -p password drop
    


  3. Поднятие дампа на hydra2:

    Code Block
    languagebash
    /opt/hydra/oracle/scripts/dump.sh -i hydra2 -p password -f hydra_dump import

    Во время импорта дампа в новую базу возможны ошибки следующего вида:

    Code Block
    languagetext
    Failing sql is:
    GRANT SELECT ON "AIS_NET"."SR_V_GOOD_SERVS" TO "NET_GOODS"
    ORA-39083: Object type OBJECT_GRANT failed to create with error:
    ORA-01917: user or role 'NET_GOODS' does not exist

    Эти ошибки не являются критичными, т.к. скрипт экспорта выгружает только схему AIS_NET. Отсутствующие роли создаются в БД отдельным скриптом в завершающей части импорта.

Работа с дампами при помощи hydra-utils в Docker

Использование контейнера Docker возможно только для операционных систем с ядром Linux версии 4 или выше. 

Алгоритм установки hydra-utils следующий:

  1. Создать директории для конфигурационных файлов

    Code Block
    languagetext
    sudo mkdir /etc/hydra/hydra-utils


  2. Создать docker-compose.yml в новой директории:
    Для СУБД Oracle 11 необходимо использовать следующий docker-compose.yml:

    Code Block
    languagebash
    title/etc/hydra/hydra-utils/docker-compose.yml
    version: '3.7'
    services:
      hydra-utils:
        container_name: hydra-utils
        image: docker.dl.latera.ru:5000/hydra-utils:11g
        network_mode: "host"
        environment:
          - TZ=${TZ}
          - ORACLE_HOME=${ORACLE_HOME}
        volumes:
          - /u01/app/oracle/product/11g:/u01/app/oracle/product/11g:ro
          - /u01/app/oracle/product/11g/network/admin/tnsnames.ora:/app/tnsnames.ora:ro


    Для Oracle 19:

    Code Block
    languagebash
    title/etc/hydra/hydra-utils/docker-compose.yml
    version: '3.7'
    services:
      hydra-utils:
        container_name: hydra-utils
        image: docker.dl.latera.ru:5000/hydra-utils:latest
        network_mode: "host"
        environment:
          - TZ=${TZ}
        volumes:
          - /u01/app/oracle/product/19c/network/admin/tnsnames.ora:/app/tnsnames.ora


    TZ - временная зона сервера. Значение переменной окружения может быть задано вручную, либо в /etc/environment. Например: 

    Code Block
    languagebash
    titleЗначение переменной TZ
    TZ="Asia/Krasnoyarsk"

    ORACLE_HOME - каталог с установленным Oracle. Задано в /etc/environment.

  3. После создания файлов конфигурации необходимо перейти в директорию и установить образ:

    Code Block
    languagebash
    titleУстановка образа контейнера
    cd /etc/hydra/hydra-utils/
    sudo docker-compose pull


Пример вызова скриптов из контейнера для переноса дампа БД с hydra на hydra2 (для Oracle 19 вместо hydra-utils нужно вызывать hydra-utils-19с)
):

  1. Снятие дампа с hydra:

    Code Block
    languagebash
    sudo docker-compose -f /etc/hydra/hydra-utils/docker-compose.yml run --rm hydra-utils dump.sh -i hydra -p password -f hydra_dump export
    


  2. Очистка hydra2:

    Code Block
    languagebash
    sudo docker-compose -f /etc/hydra/hydra-utils/docker-compose.yml run --rm hydra-utils dump.sh -i hydra2 -p password drop
    


  3. Поднятие дампа на hydra2:

    Code Block
    languagebash
    sudo docker-compose -f /etc/hydra/hydra-utils/docker-compose.yml run --rm hydra-utils dump.sh -i hydra2 -p password -f hydra_dump import


Warning
titleDDL

В ходе снятия дампа не должны выполняться DDL выражения, в том числе TRUNCATE и очистка очередей, иначе снятие дампа завершится с ошибкой ORA-01466: unable to read data - table definition has changed


Note
titleПримечание

Так как процедура снятия резервных копий с помощью утилиты expdp (скрипт dump.sh) является достаточно ресурсоемкой, снимать резервные копии БД рекомендуется в ночное время в часы наименьшей нагрузки на сервер (как правило, с 2-х до 4-х часов ночи).

...

Note
titleПримечание 4

При копировании дампа на внешнее хранилище необходимо копировать и лог экспорта (файл с суффиксом _expdp.log в каталоге с дампом)


Note
titleПримечание 5

Новые профили пользователей, отличные DEFAULT, не сохранятся при снятии дампов. Это происходит только при экспорте полного бекапа со всей БД. Подробнее: Export and Import Modes

Полный список команд для получения DDL кастомных профилей можно получить при помощи следующего SQL запроса:

Code Block
languagesql
SELECT  DBMS_METADATA.GET_DDL('PROFILE',PROFILE)
FROM    DBA_USERS
WHERE   PROFILE != 'DEFAULT'
GROUP BY PROFILE;

Для их автоматического резервирования рекомендуется использовать RMAN бекапы.




Отменить процесс экспорта/импорта дампа можно с помощью CTRL-C и команды kill_job:

...

Code Block
languagesql
DECLARE
 ch_AlterTypes  VARCHAR2(1) := 'N';
 num_MaxRetries NUMBER := 0;
 num_Counter    NUMBER := 0;
 --
 num_Retries    NUMBER;

  PROCEDURE TRY_TO_ALTER_TYPE(
    vch_VC_TYPE_NAME                  IN ALL_OBJECTS.OBJECT_NAME%TYPE)
  IS
    num_Count                         NUMBER;
  BEGIN
    SELECT COUNT(*)
    INTO num_Count
    FROM  ALL_OBJECTS
    WHERE OBJECT_NAME = vch_VC_TYPE_NAME
    AND   OBJECT_TYPE = 'TYPE';
  
    IF num_Count > 0 THEN
      EXECUTE IMMEDIATE 'ALTER TYPE "' || vch_VC_TYPE_NAME || '" COMPILE';
    END IF;
  END TRY_TO_ALTER_TYPE;

BEGIN
  IF ch_AlterTypes = 'Y' THEN
    TRY_TO_ALTER_TYPE('equipment_bind');
    TRY_TO_ALTER_TYPE('equipment_binds');
    TRY_TO_ALTER_TYPE('HYDRA_ANYDATA');
    TRY_TO_ALTER_TYPE('HYDRA_ANYDATA_TABLE');
    TRY_TO_ALTER_TYPE('application_context');
    TRY_TO_ALTER_TYPE('deferred_task');
    TRY_TO_ALTER_TYPE('command_result');
    TRY_TO_ALTER_TYPE('command_results');
    TRY_TO_ALTER_TYPE('command');
    TRY_TO_ALTER_TYPE('commands');
    TRY_TO_ALTER_TYPE('profile_attribute');
    TRY_TO_ALTER_TYPE('profile_attributes');
    TRY_TO_ALTER_TYPE('profile');
    TRY_TO_ALTER_TYPE('profiles');
    TRY_TO_ALTER_TYPE('sys_msg_line');
    TRY_TO_ALTER_TYPE('sys_msg_lines');
    TRY_TO_ALTER_TYPE('system_message');
    TRY_TO_ALTER_TYPE('system_messages');
    TRY_TO_ALTER_TYPE('service');
    TRY_TO_ALTER_TYPE('services_list');
    TRY_TO_ALTER_TYPE('account_services');
    TRY_TO_ALTER_TYPE('LOG_MESSAGE');
  END IF;
  
  -- Выбираем список объектов
  FOR rl_Object IN (
    SELECT OWNER,
           OBJECT_NAME,
           OBJECT_TYPE
    FROM   ALL_OBJECTS A
    WHERE  OBJECT_TYPE IN ('PACKAGE', 'PACKAGE BODY', 'TRIGGER', 'VIEW')
    AND    OWNER  = 'AIS_NET'
    AND    STATUS = 'INVALID'
    ORDER BY OBJECT_TYPE, OBJECT_NAME)
  -- Движение по списку
  LOOP
    num_Retries := 0;
    num_Counter := num_Counter + 1;
  
    <<retry>>
  
    -- Компилим объект
    BEGIN
      -- Разные команды для пакетов ХП и остальных типов объектов
      IF rl_Object.OBJECT_TYPE = 'PACKAGE BODY' THEN
        EXECUTE IMMEDIATE 'ALTER PACKAGE "' || rl_Object.OWNER || '"."' || rl_Object.OBJECT_NAME || '" COMPILE BODY';
      ELSE
        EXECUTE IMMEDIATE 'ALTER ' || rl_Object.OBJECT_TYPE || ' "' || rl_Object.OWNER || '"."' || rl_Object.OBJECT_NAME || '" COMPILE';
      END IF;
    EXCEPTION WHEN others THEN
      IF num_Retries < num_MaxRetries THEN
        num_Retries := num_Retries + 1;
        GOTO Retry;
      ELSE
        DBMS_OUTPUT.PUT_LINE('Ошибка: '|| rl_Object.OBJECT_TYPE || ' ' || rl_Object.OWNER || '.' || rl_Object.OBJECT_NAME);
      END IF;
    END;
  END LOOP;
  
  DBMS_OUTPUT.PUT_LINE('Total processed: ' || num_Counter);
  
  IF ch_AlterTypes = 'Y' THEN
    SYS.FIX_HYDRA_OBJECT_TYPES;
  END IF;
END;
/

И проверить наличие невалидных объектов

...

Для устранения дефекта необходимо применить Oracle патч  и повторить действия по разворачиванию дампа.

Исключением могут быть пакеты с префиксом MI_ — ядро приложения миграции (если данные объекты не используются).

Анализ БД

Перед началом использования БД необходимо выполнить полный анализ БД.

...

Code Block
languagesql
DECLARE
 num_N_JOB_ID        NUMBER := -101;
 --
 ch_Invalidate       SS_PARVALUES.C_FLAG_VALUE%TYPE;
 ch_StaleOnly        SS_PARVALUES.C_FLAG_VALUE%TYPE;
 num_AnalyzePercent  SS_PARVALUES.N_VALUE%TYPE;
BEGIN
 DBMS_STATS.SET_GLOBAL_PREFS('NO_INVALIDATE', 'FALSE');

 -- Сохранение текущих параметров
 num_AnalyzePercent := SS_PARS_PKG_S.GET_N_VALUE_BY_CODE(
   vch_VC_CODE  => 'PAR_JobAnalyzeSchema_AnalyzePercent',
   num_N_JOB_ID => num_N_JOB_ID);

 ch_StaleOnly := SS_PARS_PKG_S.GET_C_FLAG_VALUE_BY_CODE(
   vch_VC_CODE  => 'PAR_JobAnalyzeSchema_StaleOnly',
   num_N_JOB_ID => num_N_JOB_ID);

 ch_Invalidate := SS_PARS_PKG_S.GET_C_FLAG_VALUE_BY_CODE(
   vch_VC_CODE  => 'PAR_JobAnalyzeSchema_InvalidateCursors',
   num_N_JOB_ID => num_N_JOB_ID);

 -- Установка нужных параметров
 SS_PARS_PKG.SS_PARVALUES_PUT(
   num_N_PAR_ID         => SS_PARS_PKG_S.GET_PAR_ID_BY_CODE(
                             vch_VC_CODE  => 'PAR_JobAnalyzeSchema_AnalyzePercent',
                             num_N_JOB_ID => num_N_JOB_ID),
   num_N_SUBJECT_ID     => NULL,
   num_N_APPLICATION_ID => NULL,
   num_N_VALUE          => 100,
   num_N_JOB_ID         => num_N_JOB_ID);

 SS_PARS_PKG.SS_PARVALUES_PUT(
   num_N_PAR_ID         => SS_PARS_PKG_S.GET_PAR_ID_BY_CODE(
                             vch_VC_CODE  => 'PAR_JobAnalyzeSchema_StaleOnly',
                             num_N_JOB_ID => num_N_JOB_ID),
   num_N_SUBJECT_ID     => NULL,
   num_N_APPLICATION_ID => NULL,
   ch_C_FLAG_VALUE      => 'N',
   num_N_JOB_ID         => num_N_JOB_ID);

 SS_PARS_PKG.SS_PARVALUES_PUT(
   num_N_PAR_ID         => SS_PARS_PKG_S.GET_PAR_ID_BY_CODE(
                             vch_VC_CODE  => 'PAR_JobAnalyzeSchema_InvalidateCursors',
                             num_N_JOB_ID => num_N_JOB_ID),
   num_N_SUBJECT_ID     => NULL,
   num_N_APPLICATION_ID => NULL,
   ch_C_FLAG_VALUE      => 'Y',
   num_N_JOB_ID         => num_N_JOB_ID);

 COMMIT;

 -- Подготовка к выполнению задания вручную
 SS_JOBS_PKG.MANUAL_START_JOB(num_N_JOB_ID);

 -- Выполнение задания в текущей сессии
 SS_JOBS_PKG.RUN_JOB(
   num_N_JOB_ID => num_N_JOB_ID,
   ch_C_REASON  => 'M');

 DBMS_STATS.SET_GLOBAL_PREFS('NO_INVALIDATE', 'DBMS_STATS.AUTO_INVALIDATE');

 -- Возврат сохраненных параметров
 SS_PARS_PKG.SS_PARVALUES_PUT(
   num_N_PAR_ID         => SS_PARS_PKG_S.GET_PAR_ID_BY_CODE(
                             vch_VC_CODE  => 'PAR_JobAnalyzeSchema_AnalyzePercent',
                             num_N_JOB_ID => num_N_JOB_ID),
   num_N_SUBJECT_ID     => NULL,
   num_N_APPLICATION_ID => NULL,
   num_N_VALUE          => num_AnalyzePercent,
   num_N_JOB_ID         => num_N_JOB_ID);

 SS_PARS_PKG.SS_PARVALUES_PUT(
   num_N_PAR_ID         => SS_PARS_PKG_S.GET_PAR_ID_BY_CODE(
                             vch_VC_CODE  => 'PAR_JobAnalyzeSchema_StaleOnly',
                             num_N_JOB_ID => num_N_JOB_ID),
   num_N_SUBJECT_ID     => NULL,
   num_N_APPLICATION_ID => NULL,
   ch_C_FLAG_VALUE      => ch_StaleOnly,
   num_N_JOB_ID         => num_N_JOB_ID);

 SS_PARS_PKG.SS_PARVALUES_PUT(
   num_N_PAR_ID         => SS_PARS_PKG_S.GET_PAR_ID_BY_CODE(
                             vch_VC_CODE  => 'PAR_JobAnalyzeSchema_InvalidateCursors',
                             num_N_JOB_ID => num_N_JOB_ID),
   num_N_SUBJECT_ID     => NULL,
   num_N_APPLICATION_ID => NULL,
   ch_C_FLAG_VALUE      => ch_Invalidate,
   num_N_JOB_ID         => num_N_JOB_ID);

 COMMIT;
END;
/