Введение
В первой части статьи была рассмотрена основная проблема при миграции СУБД Oracle с RISC-платформ на Linux x86 - различие в форматах хранения (Endian) и необходимость конвертации блоков в файлах данных при миграции. Также кратко была описана технология миграции с помощью транспортируемых табличных пространств, включая вариант с инкрементальными резервными копиями, который позволяет снизить время простоя (downtime) при миграции.
В второй части статьи был описан алгорим миграции с помощью технология Full Transportable Export/Import (FTEX) с использованием скриптов M5, поставляемых компанией Oracle.
Несмотря на значительное упрощение миграции с помощью технологии Full Transportable Export/Import и скриптов M5, опыт автора показывает, что при миграции реальных производственных баз Oracle, возникает ряд проблем.
В заключительной, третьей части статьи, будут описаны эти проблемы и приведены возможные варианты их решения.
Подготовка исходной БД для миграции Перед тем как начинать финальный этап миграции (перевод на исходной БД табличных пространств в read only и снятие финального инкрементального бэкапа) рекомендуется выполнить следующие действия:
-
Собрать статистику по словарю и по фиксированным объектам (dictionary и fixed objects statistics), она важны для производительности Data Pump:
begin dbms_stats.gather_fixed_objects_stats; dbms_stats.gather_dictionary_stats; end;
проверить, что на исходной БД включена технология Block Change Tracking (BCT) - для ускорения получения инкрементальных бакапов;
-
отключить менеджер ресурсов (resource manager):
alter system set resource_manager_plan='';
-
отключить все maintenance windows в maintenance window-группе:
select window_name from dba_autotask_window_clients; exec dbms_scheduler.disable(name => 'SYS.MONDAY_WINDOW'); exec dbms_scheduler.disable(name => 'SYS.TUESDAY_WINDOW'); ... exec dbms_scheduler.disable(name => 'SYS.SUNDAY_WINDOW
остановить все автоматические задания (Jobs);
для того чтобы избежать ожиданий (waits) вызваных resize-операциями в SGA, следует проверить что размер STREAM_POOL не меньше чем 512M.
Длительный простой для БД, содержащих большое количество объектов в словаре
Проблема связана с тем, что в случае если БД содержит большое количество объектов (десятки тысяч и более), то есть имеет большой объем словаря (Oracle Diсtionary), экспорт/импорт метаданных при заключительном шаге миграции занимает длительное время.
Для решения этой проблемы, следует метаданные на целевую БД копировать заранее с помощью скриптов развертывания приложения, если их нет - с помощью Oracle Datapump Export Utility (параметр content=metadata_only утилиты expdp). При переносе метаданных следует также исключить определения сегментов с помощью параметра EXCLUDE утилиты Oracle Datapump Export (expdp), поскольку они будут переносится на финальном этапе с помощью подключения перемещаемых табличных пространств к целевой БД на Linux x86.
При использовании FTEX, перенос метаданных, кроме определений сегментов, также можно запретить с помощью параметра EXCLUDE утилиты expdp.
После подключения табличных пространств к целевой БД, следует перекомпилировать все PL/SQL-оъбъекты (пакеты, функции, процедуры, триггеры и т.д.) с помощью системного скрипта utlrp.sql, поскольку эти объекты находятся в невалидном состоянии (INVALID) - были созданы когда сегментов (таблиц и индексов) в целевой БД еще не было.
Разумеется, после того как метаданные скопированы на целевую БД, на исходной БД следует запретить изменение определений объектов. Это можно сделать административным способом (запретить "выкатывать" изменения на продуктивную БД), либо с помощью DDL-триггера, который будет выбрасывать исключение (exception) на любую пользовательскую DDL-операцию.
В вышеприведенном способе уменьшения времени простоя есть тонкий нюанс, связанный с последовательностями (sequences).
Дело в том, что если создавать последовательности на целевой БД заранее, то к моменту переключения на БД на Linux x86, на продуктивной БД на RISC-сервере, их значения будут уже другими - будут иметь бОльшие значения. Ведь, ведь после создания последовательностей на сервере Linux x86, текущая продуктивная БД на RISC-сервере продолжала свою работу !
![Рис 1. Расхождение значений последовательностей при опережающем копировании метаданных Рис 1. Расхождение значений последовательностей при опережающем копировании метаданных](https://habrastorage.org/getpro/habr/upload_files/0af/3b3/09e/0af3b309ebdbfc293816317c90685f04.jpg)
Для выравнивания текущих значений последовательности на целевой БД с значениями на исходной БД на RISC-сервере, был разработан скрипт reset_seq.sql Этот скрипт выполняется на целевой БД, сразу после того как приложение на исходной БД остановлено и началась выгрузка метаданных сегментов. Начиная с Oracle Database 18c сдвинуть текущее значение последовательности можно простой командой ALTER SEQUENCE <имя последовательности> RESTART START WITH <новое <значение последовательности>
Длительный простой для БД, содержащих большое количество сегментов
Если в перемещаемых табличных пространствах содержится большое количество сегментов (сотни тысяч и более), возникает длительный простой при экспорте/импорте метаданных сегментов (операции unplug/plug табличных пространств).
Дело в том, что появления до Oracle Database 21c, экспорт/импорт метаданных для перемещаемых табличных пространств работает только в один поток.
Особенно это критично для больших ERP-систем SAP R/3 и Oracle E-Business Suite, базы данных которых содержат миллионы сегментов.
Для таких БД, операции выгрузки и загрузки метаданных сегментов, могут занимать многие часы.
Для решения этой проблемы можно посоветовать несколько способов, которые могут применяться совместно.
Разделить БД на несколько замкнутых множеств табличных пространств и мигрировать их параллельно
Идея заключается в том, чтобы все пользовательские табличные пространства разделить на несколько замкнутых множеств (self-contained), и затем мигрировать их одновременно.
Если выделить такие множества c ходу не удается, например, все сегменты находятся в одном большом табличном пространстве, то можно создать новые табличное пространство и перенести туда сегменты не имеющие связей с другими табличными пространствами.
Для онлайнового перемещения сегментов используются команды alter table ... move online, alter index ... rebuild online, alter table ... move lob, либо пакет DBMS_REDEFINITION если версия СУБД Oracle не поддерживает перемещение сегментов в online.
Для одного из проектов автору пришлось разработать набор скриптов для онлайнового перемещения сегментов из одного табличного пространства в другое.
После миграции, сегменты в новых табличных пространствах можно вернуть обратно, если, конечно, такое требование присутствует.
Следует отметить, что для вышеописанного способа применить технологию Full Transportable Export/Import не получится, поскольку она мигрирует целиком все пользовательские табличные пространства. В этом случае следует применять обычную технологию транспортируемых табличных пространств c инкрементальными резервными копиями и perl-скрипты V4 от компании Oracle.
Удалить небольшие индексы на исходной БД перед финальным шагом и пересоздать на целевой БД
Этот способ прост в реализации и позволяет значительно снизить количество сегментов для миграции, а значит и время простоя на экспорт/импорт метаданных сегментов на финальном шаге миграции.
Перед снятием заключительного инкрементального бэкапа на исходной БД на RISC-сервере, удаляются небольшие индексы, размер которых не превышает нескольких гигабайт (размер подбирается исходя из допустимого времени простоя и производительности оборудования на целевой БД). После подключения сконвертированных табличных пространств на Linux-сервере, эти индексы заново пересоздаются с помощью оператора СREATE INDEX ... ONLINE.
Для автоматизации процесса автор использует разработанный скрипт del_small_ind.sql, который выгружает DDL-операторы создания индексов в отдельный файл и удаляет их из исходной БД, выключая ограничения целостности UNIQUE и PK, если удаляемый индекс нужен для поддержки их работоспособности. Одновременно скрипт del_small_ind.sql генерирует скрипт create_small_ind.sql создания этих индексов и включения соответствующих ограничений целостности на целевой БД.
Скрипт del_small_ind.sql запускается после остановки приложения на исходной БД, перед операцией перевода табличных пространств в режим Read Only. Скрипт create_small_ind.sql запускается на целевой БД после подключения сконвертированных табличных пространств.
Удалить вспомогательные (промежуточные) таблицы на исходной БД перед финальным шагом и пересоздать на целевой БД
В большом приложения часто присутствует большой набор таблиц, которые хранят только промежуточные данные. Например, staging-таблицы в информационно-аналитических хранилищах данных. В процессе работы приложения, содержимое таких таблиц удаляется и "перезаливается" заново.
Такие таблицы тоже можно удалить из исходной БД, перед переводом табличных пространств в режим read-only. Следует заранее создать эти таблицы на целевой БД с помощью соответствующих команд CREATE TABLE. Для автоматизации этой операции удобно использовать утилиту expdp с параметрами TABLES и CONTENT=METADATA_ONLY, и далее импортировать полученный дамп в исходную БД с помощью утилиты impdp.
Заранее перенести статические справочные таблицы
Идея заключается в том, чтобы заранее перенести статические таблицы на БД на Linux x86 сервере. Статические таблицы - имеются в виду таблицы, которые не меняются, по крайней мере на период миграции можно запретить в них изменения. В качестве примера можно привести справочник валют в финансовом приложении, или справочник тарифов услуг в биллинговой системе.
Такие таблицы удаляются из исходной БД, перед переводом табличных пространств в режим read-only. Следует заранее создать эти таблицы на целевой БД с помощью соответствующих команд CREATE TABLE и перенести в них данные из исходной БД.
Для автоматизации этой операции удобно использовать утилиту expdp с параметрами TABLES, и далее импортировать полученный дамп в исходную БД с помощью утилиты impdp.
Следует обратить внимание, что эти статические таблицы придется загрузить в целевую БД в новые табличные пространства (ведь табличных пространств из исходной БД еще нет!) - их нужно заранее создать на целевой БД, и импортировать в них эти таблицы с помощью параметра REMAP_TABLESPACES утилиты impdp.
Для того, чтобы гарантировать неизменность этих таблиц, рекомендуется на исходной БД перевести их в режим read only.
После переключения на целевую БД, нужно не забыть вернуть эти таблицы в режим read write
Удалить неиспользуемые таблицы
Очень часто в больших приложениях, которые постоянно развиваются, в схеме данных скапливаются неиспользуемые таблицы, например: резервные копии таблиц, таблицы для функционала, который уже удален из приложения. Поэтому перед проектом миграции рекомендуется провести очистку схем приложения от неиспользуемх таблиц.
У автора был опыт проекта, когда проблема длительного простоя на экспорт-импорт метаданных сегментов при миграции СУБД Oracle с RISC на Linux x86 была решена именно этим способом - удалением неиспользуемых таблиц, скопившихся за долгие годы изменения схемы данных приложения.
Временный перенос системного табличного пространства и онлайн редологов на RAM-диск
Снизить время импорта метаданных сегментов в целевую БД можно еще одним оригинальным способом: уменьшить объем SGA для экземпляра на целевом сервере Linux x86, на освободившийся объем памяти создать RAM-диск, затем перенести на него файлы табличного пространства SYSTEM и онлайновые редологи.
Дело в том, что в процессе подключения новых табличных пространств и перекомпиляции PL/SQL-кода в целевой БД, основной объем изменений происходит именно в системном табличном пространстве и, очевидно, в online redolog. Скорость доступа к нем резко возрастет, если эти файлы будут размещаться в памяти.
На завершающем этапе миграции, файлы табличного пространства SYSTEM и онлайновых редологов переносятся на обычный диск, экземпляр останавливается, RAM-диск удаляется и освободившееся память возвращается в объем SGA, c последующим стартом экземпляра.
Очистка мусорной корзины (Recycle Bin) и дематериализация пустых сегментов на целевой БД
Конечно, нужно не забыть очистить мусорную корзину, если она включена:
SQL> purge dba recyclebin;
Также можно рекомендовать удалить пустые сегменты на исходной БД, то есть перевести их в режим отложенного создания (deffered segment creation):
exec dbms_space_admin.drop_empty_segments;
В этом случае сам сегмент будет удален из табличного пространства, однако его описание в словаре БД останется.
Экономия времени происходит за счет того, что происходит уменьшение объема метаданных сегментов, поскольку не нужно сохранять в дамп-файле описание сегментов и не нужно затем создавать сегмент на целевой БД при подключении табличного пространства
Миграция директорий (Directory) и BFILE
Очевидно, что содержимое каталогов файловой системы на исходном сервере, автоматически не переносится на целевой сервер.
Поэтому, если приложение или инструменты ДБА, используют ссылки на каталоги в БД Oracle - объекты DIRECTORY и, тем более, внешние LOB-объекты (BFILE), то необходимо вручную скопировать их на целевой сервер, предварительно создав на нем каталоги на файловой системе и аналогичные ссылки на них в БД (directory). Содержимое используемых каталогов с исходного сервера следует переносить на целевой сервер только после того как приложение остановлено.
Для автоматизации проверки использования директорий в исходной БД и генерации DDL-скрипта для их создания на целевой БД, автором был разработан и применяется скрипт check_dirs.sql
Миграция очередей Oracle Advanced Queuing
При использовании миграции с помощью переносимых табличных пространств и скриптов V4, переносятся только таблицы с сообщениями очередей, сами объявления очередей не переносятся в ходе expdp/impdp операции. Для решения этой проблемы, очереди на приемнике нужно пересоздавать заново, определив затем соответствующие таблицы с сообщениями, которые были смигрированы с БД-источника, подробнее об этом в документе "How Advanced Queueing (AQ) Objects Are Exported And Imported. (Doc ID 2291530.1)"
Даже при использовании скриптов M5 и FTEX, очень часто происходят проблемы с экспортом/импортом очередей Advanced Queuing - они очень часто не переносятся корректно.
Рекомендуется, в любом случае, определения очередей AQ переносить отдельно, затем определяя для каждой очереди соответствующую таблицу с сообщениями, после подключения табличных пространств на целевой БД.
Для автоматизации процесса выгрузки скрипта создания очередей и скрипта подключения таблиц к вновь созданной очереди на целевой БД автором был разработан скрипт recreate_queues.sql.
Ошибка при миграции большого количества файлов данных
Автор в одном из проектов столкнулся с этой неприятной проблемой.
Если БД имеет большой размер и состоит из большого количество файлов данных, а такое происходит при использовании табличных пространств созданных в режиме smallfile, то при импорте метаданных сегментов с БД-источника возникает ошибка: ORA-01240: too many data files to add in one command.
Проблема связана с тем, что при импорте метаданных сегментов, строка с полными именами файлов данных должна умещаться в одну redo-запись в лог-файле. Описание этой проблемы приведено в документе на сайте службы технической поддержки Oracle Support: "ORA-39123 ORA-1240 Error On Import Of Transportable Tablespace (Doc ID 740983.1)".
Решение, предлагаемое в этом документе, простое: переименовать файлы данных сократив их имена, путь на файловой системе можно сократить сделав короткий символический линк на имя файла и переименовать имя файла данных в СУБД на новое имя с этим символическим линком.
Если файлов данных слишком много, и строка с полным списком файлов все равно не помещается в одну redo-запись, то можно порекомендовать создать табличные пространства в режиме bigfile и перенести туда все сегменты. Для решения этой проблемы автору пришлось разработать скрипт move_segments.sql для онлайного перемещения сегментов в новые bigfile табличные пространства.
Перенос статистики до миграции табличных пространств
При использовании для миграции скриптов M5, есть небольшая особенность связанная с переносом статистики для SQL-оптимизатора Oracle: статистика не переносится в целевую БД (по умолчанию передается параметр exclude=statistics в утилиту expdp).
В этом есть смысл, поскольку статистику следует переносить заранее - это значительно сэкономит время простоя при миграции.
На исходной БД следует выгрузить текущую актуальную статистику в stage-таблицу.
![Рис 2. Выгрузка статистики и ее копирование на целевой сервер Рис 2. Выгрузка статистики и ее копирование на целевой сервер](https://habrastorage.org/getpro/habr/upload_files/ad6/e89/b15/ad6e89b1585aee05ce2417395b6ade37.jpg)
Перенос stage-таблицы с статистикой с исходной БД на целевую производится через обычный Datapump Export, либо stage-таблица будет перенесена в ходе миграции соответствующего пространства автоматически.
Проверка метаданных после миграции
Критически важно, после того как табличные пространства успешно подключены к целевой БД на Linux x86 и PL/SQL-код скомпилирован, тщательно проверить что ничего не "сломалось" и не "потерялось по дороге":
проверить блоки данных на отсутствие повреждений (corrupted blocks) с помощью утилиты RMAN (validate database check logical);
проверить отсутствие логических повреждений в Oracle Dictionary с помощь системного скрипта hcheck.sql - "Script to Check Data Dictionary for Known Problems (Doc ID 136697.1)";
проверить состояние всех объектов в словаре: не появились ли объекты в невалидном состоянии (INVALID) и все ли объекты были перенесены, с этой целью автором был разработан скрипт check_objects.sql для сверки состояний всех объектов,кроме сегментов, на исходной и целевой БД, с контролем их соответствия c исходной БД;
проверить, что все сегменты, которые были в исходной БД, также присутствуют и в целевой БД, для этого используется разработанный автором скрипт check_segments.sql ;
собрать статистику по словарю и по фиксированным объектам.
Заключение
Проект по миграции СУБД Oracle с платформы RISC на Linux x86 только на первый взгляд кажется простой задачей.
Конечно, для небольших БД, для которых допустимо большое время простоя (downtime), проще всего для этой цели применять технологию экспорт-импорта данных Oracle Datapump.
Однако для больших БД, содержащих большое количество объектов, и для которых бизнес регламентирует небольшое время простоя, необходимо применять другие технологии.
Рассмотренные в статье технологии Oracle Transportable Tablespace с инкрементальными резервными копиями и Oracle Full Transportable Export/Import позволяют решить эту задачу.
Это сложные технологии, но при тщательной подготовке, тестировании и наличии готовых инcтрументов, задача миграции вполне решаема.
За рамками статьи остались вопросы сайзинга целевого сервера на Linux x86 и тестировании производительности при миграции.
Это большие темы и, видимо, они потребуют написания отдельной статьи.
Автор выражает благодарность компании ЭЛЬКАРО за предоставленный для тестирования сервер на платформе Sun Solaris 11.4 for SPARC.
Игорь Мельников
Независимый консультант