Источник: «Инфосистемы Джет»
Источник: «Инфосистемы Джет»

Недавно мы написали о том, насколько экономически разумно «переезжать» с Oracle на PostgreSQL. В этом материале хотели бы поделиться практическим опытом, как осуществить миграцию небольшой СУБД, и какие подводные камни вас могут ожидать при этом.

Трудности перевода

Один из наших крупных клиентов — российский банк — захотел мигрировать небольшую типовую базу данных с Oracle на Postgres. В целом, забегая вперед, можно утверждать, что миграция прошла в штатном режиме, однако мы столкнулись с несколькими важными нюансами, которые рекомендуем учитывать коллегам.

Основная проблема, возникшая при переезде, была связана с mview. В нем была прописана функция regexp_replace. Характерно, что в Oracle она организована по одному принципу, а в PostgreSQL — совсем иначе. Однако функция в обоих СУБД называется одинаково, и из-за этого вывод запроса был некорректным. Нам пришлось проявить смекалку в поисках альтернативного варианта. И он нашелся! Речь идет о расширении под Postgres, которое называется orafce. Все бы было хорошо, но у этого расширения есть определенный нюанс, из-за которого нам надо было немного переписывать код, добавив в эту функцию «oracle.». При помощи orafce можно успешно использовать операторы дат Oracle в Postgres. Более подробно, как использовать это расширение, можно почитать по ссылке https://github.com/orafce/orafce. Так, в решении нашей задачи пришлось изменить в выгруженной схеме smallint на Boolean, поскольку по умолчанию для логического типа данных в схеме oracle использовался NUMBER(1).

Как мы действовали

Ниже последовательность наших действий при миграции схемы в хронологическом порядке.

Устанавливаем ora2pg и необходимые компоненты:

rpm -ivh oracle-instantclient12.2-basic-12.2.0.1.0-1.x86_64.rpm
rpm -ivh oracle-instantclient12.2-devel-12.2.0.1.0-1.x86_64.rpm
rpm -ivh oracle-instantclient12.2-jdbc-12.2.0.1.0-1.x86_64.rpm
rpm -ivh oracle-instantclient12.2-sqlplus-12.2.0.1.0-1.x86_64.rpm

yum install -y wget

wget https://yum.oracle.com/RPM-GPG-KEY-oracle-ol7 -O /etc/pki/rpm-gpg/RPM-GPG-KEY-oracle

yum install -y perl perl-CPAN perl-DBI perl-Time-HiRes perl-YAML perl-local-lib make gcc

yum install -y perl-App-cpanminus

cpanm CPAN::Config
cpanm CPAN::FirstTime

export LD_LIBRARY_PATH=/usr/lib/oracle/12.2/client64/lib
export ORACLE_HOME=/usr/lib/oracle/12.2/client64

perl -MCPAN -e 'install DBD::Oracle'
perl -MCPAN -e 'install DBD::Pg'

tar zxf ora2pg-23.1.tar.gz && cd ora2pg-21.1 && perl Makefile.PL && make && make install
ora2pg --project_base /migration/ --init_project test_project

Изменяем config созданного проекта. Редактируем подключение к Oracle:

ORACLE_DSN  dbi:Oracle:host=*****;sid=***;port=1521
ORACLE_USER *****
ORACLE_PWD *****

Редактируем подключение к Postgres:

PG_DSN      dbi:Pg:dbname=***;host=*****;port=5432
PG_USER postgres
PG_PWD  *****

Указываем схему в Oracle и предполагаемую схему в Postgres:

SCHEMA  ****
PG_SCHEMA ****
ora2pg -t SHOW_TABLE -c config/ora2pg.conf

Остальные настройки конфигурации, чтобы не повторяться, можно легко найти в документации к ora2pg.

Далее редактируем pg_hba и перезапускаем Postgres:

host all all 0.0.0.0/0 md5
systemctl restart postgresql-14

Проверяем подключение к схеме в базе Oracle и оцениваем миграцию:

ora2pg -t SHOW_TABLE -c config/ora2pg.conf
ora2pg -t SHOW_REPORT --estimate_cost -c config/ora2pg.conf export_schema.sh

Важно, что данные команды мы запускали в главной папке проекта. Далее запускаем ./export_schema.sh для выгрузки схемы.

Так как в нашем случае нужно было заранее использовать orafce для функции regexp_replace, нам пришлось предварительно создать базу и пользователя в Postgres и загрузить расширение CREATE EXTENSION orafce.

После запуска ./import_all.sh -h localhost -d test -o test -U postgres –I несколько раз возникали ошибки импорта, которые мы впоследствии исправили. В нашем варианте большинство ошибок было в коде mview.

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

psql -h hostname -U username -d dbname < /migration/schema/tables/INDEXES_table.sql
psql -h hostname -U username -d dbname < /migration/schema/tables/CONSTRAINTS_table.sql
psql -h hostname -U username -d dbname < /migration/schema/tables/FKEYS_table.sql
psql -h hostname -U username -d dbname < /migration/schema/triggers/trigger.sql

Результат миграции. Стоит ли игра свеч?

После тестирования нам пришлось исправить некоторые проблемы в базе, например, рассинхронизацию sequence. Однако в целом миграция прошла успешно. И результат вместе с базой мы благополучно передали заказчику. Таким образом, если объем данных в таблицах исчисляется сотнями гигабайт, мы рекомендуем, при наличии ИТ-ресурсов, запускать миграцию при помощи ora2pg в несколько потоков. Подробная информация о том, как это сделать, есть в документации к ora2pg. Это действительно сильно ускоряет выгрузку и загрузку данных.

Схемы малого и среднего объема переносить на Postgres достаточно легко, и в текущее время эта задача особенно актуальна. Мы полагаем, что более крупные схемы в несколько терабайт разумнее мигрировать при помощи goldengate + ora2pg. При этом ora2pg – миграция структуры, а goldengate – миграция данных.

Делали ли вы миграции СУБД похожего объема? С какими трудностями пришлось столкнуться и, главное, как их удалось преодолеть?

Jet Service Team

Комментарии (11)


  1. Isiirk
    13.09.2022 10:58
    +3

    Обычно на Oraclе много кода бизнес-логики выполнено на PL/SQL в хранимых процедурах, я так понимаю вы перенесли только табличные данные?


    1. uroborus_kulikov
      13.09.2022 12:13

      Все верно.


    1. Sleuthhound
      13.09.2022 12:13
      +1

      Вероятно там было минимум кода, поэтому все так удачно.

      На самом деле проблема тут не в переезде, а дальнейшей поддержки PostgreSQL, т.к. по Oracle очень много специалистов разного уровня и есть из чего выбрать, а по PostgreSQL специалистов очень мало и они дорогие, особенно те, кто знает внутрянку PostgreSQL.


      1. uroborus_kulikov
        13.09.2022 12:57
        +1

        Не совсем согласен в том что специалистов по postgresql мало...тут скорее вопрос в квалификации таких специалистов. И как раз такие малые проекты позволяют узнавать нюансы и постепенно увеличивать сложность для обучения, повышая тем самым квалификацию. Уже многие компании экспериментируют с миграцией Oracle и mssql на другие продукты opensorce. И эта тенденция как мне кажется будет только нарастать. А вот на что мигрировать, этот вопрос остаётся открытым. И зависит от специфики проекта.


        1. Sleuthhound
          13.09.2022 19:52

          Третий месяц ищем хотя бы джуна по постгрес, зп 160-200 т.р. , прособеседовали уж 5 человек и нииичего, по знаниям у них ооочень все вяло, но амбиции гора. Самое фиговое - люди просто не хотят учиться, денег хотят, а рвения к познаниям нуль.


    1. FlyingDutchman
      13.09.2022 16:34

      Видел оракловскую базу размером в 350TB (с приростом в 20-30TB/месяц), в которой было 0 логики и 0 строк PL/SQL кода. Упрощенное описание базы - просто огромное хранилище данных: объекты в BLOBах + описания объектов. Нельзя же считать бизнес-логикой автоматическое ежедневное создание date range партиций самим Ораклом? Ну да, 2-нодовый RAC с тремя Standby базами в разных датацентрах, ZFS-накопители, использующиеся для архивных read-only партиций и т.п.


  1. polar_yogi
    13.09.2022 12:52
    +1

    Интересно услышать хоть какую-нибудь оценку - как изменилась скорость работы приложения после миграции данных, изменился ли объем БД после миграции, изменились ли требования к hardware.


    1. uroborus_kulikov
      13.09.2022 13:06
      +1

      Так как это была база малого объема скорость работы приложения практически не изменилась. Если бы предполагалась высокая нагрузка, использовались бы такие инструменты как pgbouncer и patroni. Часть нагрузки можно было бы снизить, отправив запросы чтения на slave. В любом случае, мы будем развиваться в данном направлении и при миграции крупных баз обязательно напишем.


    1. PaulIsh
      14.09.2022 16:08

      С Oracle на Pg не мигрировал. С Firebird мигрировал. Мигрировали с Fb 2.5 на Pg 10. По самому переносу данных и повторении структур - ничего особенного. Написали руками код миграции на node. Из особенностей только булевы поля добавились. А вот все триггеры, процедуры пришлось переписывать с нуля. И по ходу эксплуатации иногда ловить ошибки, что в Pg в триггерах нужно возвращать new, а в Fb не нужно и местами при ручном переносе это не замечалось.

      На Pg был ощутимый рост скорости запросов при тех же индексах. Некоторые запросы ускорились в десятки раз (как помню, Firebird не очень любил not in () условия). Также на pg для аналитических запросов (отчеты, где кучи join-ов, аггрегация, подселекты) настроили master-slave репликацию, что позволило еще сильнее разгрузить оперативную базу.


  1. Loskore
    15.09.2022 18:16

    Мы в данный момент мигрируем с MS-SQL(T-Sql) на Pg12. И откровенно признаюсь, это просто адище в прямом смысле. Сам проект легаси, в котором накопилось бизнес логики за всё время существования (138 страдж процедур и 9 функций). И из-за этого каждый раз как в "первый раз": синтаксис отличается, очень важных языковых конструкций и команд(типа Merge) попросту нет. Запрос в Pg в отличии от T-Sql не может иметь переменных, и создание переменных типа "Table" не завезли (приходится заниматься колдунством ???? с массивами собственных типов) . Даже есть ньюансы в работе одной и той же ОРМ с СУБД от мягкомягких и pg. Так что, всём желаю крепко держать "бубен" с своих руках????, он нам ещё пригодиться.


    1. edo1h
      16.09.2022 06:51

      команд(типа Merge)

      merge вроде бы будет в 15-ой версии, пока есть вот такое:
      https://www.depesz.com/2015/05/10/waiting-for-9-5-add-support-for-insert-on-conflict-do-nothingupdate/