This article is in English Working with the DB Dumps |
Для работы с дампами БД следует пользоваться специальным скриптом dump.sh
, который устанавливается при помощи deb пакета hydra-utils.
Этот пакет совместим с операционными системами Debian 9
и ниже. Для операционной системы Oracle Linux необходимо использовать отдельный Docker-
контейнер.
У скрипта для работы с дампами БД существуют следующие варианты запуска:
/var/oradata/dumps
)./var/oradata/dumps
). После импортирования флаг «Признак промышленной базы данных» сбрасывается.Дополнительные параметры вызова скрипта:
При установке hydra-utils скрипт снятия дампов устанавливаются в следующую директорию - /opt/hydra/oracle/scripts
. Скрипт обязательно следует вызвать под пользователем oracle с инициализированным окружением. Инициализировать окружение для пользователя oracle с помощью sudo можно выполнить следующим образом:
sudo -u oracle -i |
Пример вызова скрипта для переноса дампа БД с hydra на hydra2:
Снятие дампа с hydra:
/opt/hydra/oracle/scripts/dump.sh -i hydra -p password -f hydra_dump export |
Очистка hydra2:
/opt/hydra/oracle/scripts/dump.sh -i hydra2 -p password drop |
Поднятие дампа на hydra2:
/opt/hydra/oracle/scripts/dump.sh -i hydra2 -p password -f hydra_dump import |
Во время импорта дампа в новую базу возможны ошибки следующего вида:
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. Отсутствующие роли создаются в БД отдельным скриптом в завершающей части импорта.
Использование контейнера Docker
возможно только для операционных систем с ядром Linux
версии 4 или выше.
Алгоритм установки hydra-utils
следующий:
Создать директории для конфигурационных файлов
sudo mkdir /etc/hydra/hydra-utils |
Создать docker-compose.yml
в новой директории:
Для СУБД Oracle 11 необходимо использовать следующий 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:
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
. Например:
TZ="Asia/Krasnoyarsk" |
ORACLE_HOME
- каталог с установленным Oracle. Задано в /etc/environment
.
После создания файлов конфигурации необходимо перейти в директорию и установить образ:
cd /etc/hydra/hydra-utils/ sudo docker-compose pull |
Пример вызова скриптов из контейнера для переноса дампа БД с hydra
на hydra2
(для Oracle 19 вместо hydra-utils нужно вызывать hydra-utils-19с)
):
Снятие дампа с hydra:
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 |
Очистка hydra2:
sudo docker-compose -f /etc/hydra/hydra-utils/docker-compose.yml run --rm hydra-utils dump.sh -i hydra2 -p password drop |
Поднятие дампа на hydra2:
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 |
В ходе снятия дампа не должны выполняться DDL выражения, в том числе TRUNCATE и очистка очередей, иначе снятие дампа завершится с ошибкой |
Так как процедура снятия резервных копий с помощью утилиты expdp (скрипт |
При выполнении любого drop (даже отдельных схем) все открытые соединения с базой будут принудительно завершены |
После выполнения поднятия дампа необходимо проверить лог импорта (файл с суффиксом _impdp.log в каталоге с дампом) на наличие ошибок |
При копировании дампа на внешнее хранилище необходимо копировать и лог экспорта (файл с суффиксом _expdp.log в каталоге с дампом) |
Новые профили пользователей, отличные Полный список команд для получения DDL кастомных профилей можно получить при помощи следующего SQL запроса:
Для их автоматического резервирования рекомендуется использовать RMAN бекапы. |
Отменить процесс экспорта/импорта дампа можно с помощью CTRL-C
и команды kill_job
:
... . . exported "AIS_NET"."SS_JOB_LOGS" 635.2 MB 1550063 rows . . exported "AIS_NET"."SD_PROCESSING_REQUESTS_T" 563.8 MB 7204 rows . . exported "AIS_NET"."SD_MV_DOCUMENTS" 479.7 MB 3247473 rows ^C Export> kill_job Are you sure you wish to stop this job ([yes]/no): yes |
Выполнять под пользователем БД |
После поднятия дампа необходимо убедиться что в базе данных нет невалидных объектов.
Для этого необходимо выполнить скрипт компилляции
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; / |
И проверить наличие невалидных объектов
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; |
В случае, если в базе есть невалидные объекты, это может быть вызвано дефектом СУБД Oracle Bug 18881811 - Data Pump Import of Wrapped PLSQL Corrupts the Body
Для устранения дефекта необходимо применить Oracle патч и повторить действия по разворачиванию дампа.
Исключением могут быть пакеты с префиксом MI_ — ядро приложения миграции (если данные объекты не используются).
Перед началом использования БД необходимо выполнить полный анализ БД.
Для этого необходимо выполнить скрипт, приведенный ниже.
Следует учесть что анализ БД может занимать весьма продолжительное время, поэтому рекомендуется выполнять его напрямую на сервере из sqlplus с использованием оконного менеджера, например screen (это позволит скрипту доработать даже в случае неожиданного обрыва связи с компьютером администратора)
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; / |