LINUX.ORG.RU

Миграция БД oracle -> postgres, best practices


1

3

Есть задача - написать скрипт, который будет мигрировать с Оракла в Постгрес. Сначала одноразово всю базу, потом - только дельта-обновления.

Зачем это нужно заказчику, почему он решил платить разрабу N бабла вместо того, чтобы купить тулзу за сто баксов - не знаю, может он наркоман. Неважно.

Короче, поделитесь методами миграции? Особенно интересен перенос структуры схем, foreign keys, etc

Пока есть идея как-нибудь извратиться над Гибернейтом: вначале вывести структуру БД в жаваклассы с помощью Hibernate Reverse Engineering, а потом использовать их как прокси для перекидывания туда-сюда. Но Hibernate Tools дырявы. Не уверен, что это хорошая идея...

Может, есть какие-нибудь готовые скрипты со _внятным_ исходником? Т.е. написанные НЕ на перле, в которых много комментариев, итп

Кто-нибудь этим уже занимался из лоровцев

★★★★☆
Ответ на: комментарий от ukr_unix_user

там написано про синтаксис скриптов и stored procedures. Для случая, когда нужно смигрировать SQL-запросы. Там много еще на сайте чего про это понаписано.

У меня - другой случай. Есть готовая развёрнутая БД. Нужно перенести схемы с данными. Автоматически.

(Т.е. вывести DDL и ручками смигрировать - не подходит, там многие сотни таблиц. Да и записи с помощью тупого вывода в SQL мигрировать некошерно - объем данных в сотнях гигабайт, чтобы где-то сохранить SQL-дамп придется покупать рейд и двадцать килограммов жестких дисков).

stevejobs ★★★★☆
() автор топика
Ответ на: комментарий от stevejobs

на сколько хищная там схема?

чем не подходит для создания схемы ora2pg?

данные не обязательно дампить, можно в простом скрипте с одной селектить в другую инсертить. Если время позволяет.

ukr_unix_user ★★★★
()

Сдаётся мне, что кому-то тут светит работа по рассматриванию под микроскопом каждого типа, триггера, процедуры и тыпы. Повезет если соответствующие сущности будут. Вообщем, удачи.

ilovewindows ★★★★★
()
Ответ на: комментарий от ukr_unix_user

чем не подходит для создания схемы ora2pg?

заказчик хочет, чтобы я написал это с нуля, без привлечения внешних тулзов =)

в принципе, да, хороший совет. В ora2pg перл, но перл с комментариями, в котором можно разобраться с десятью тоннами самогона.

а еще какие-нибудь хорошие тулзы кроме ora2pg есть? .NET, Java, Python?

можно в простом скрипте с одной селектить в другую инсертить

говорят, в оракуле есть некие датастримы, но я пока не асилил как их прикрутить для наших целей :(

на сколько хищная там схема?

денормализованная каша, сгенерированная генераторами кода. И хотя там по идее не должно быть ничего агрессивного, черт знает, какой логикой пользовался генератор и его автор. Исходники генератора есть, но тут количество самогона уже измеряется килотоннами, потому что он написан на M2.

stevejobs ★★★★☆
() автор топика
Последнее исправление: stevejobs (всего исправлений: 1)
Ответ на: комментарий от stevejobs

Java,

у господ из интерпрайздб есть некий MigrationToolkit написан на java. разобрать и посмотреть как реализовано, думаю разберёшься.

ukr_unix_user ★★★★
()
Ответ на: комментарий от stevejobs

в общем случае тулзовина должна иметь сдел вид.

берём из ALL_TAB_COLUMNS имя поля, тип поля, размер поля, null не null, меняем типы в соответствии ORACLE-PG,формируем create table.

из dba_constraints берём constraints и формируем alter table примерно по таким правилам

if (constraint.getType() == 'P') {
      sql = sql + "ALTER TABLE " + constTableName + " ADD CONSTRAINT " + constraint.getName(true) + " PRIMARY KEY (";

      for (int i = 0; i < constraint.getColumns().size(); i++) {
        sql = sql + constraint.getColumns().get(i).getName();
        if (i < constraint.getColumns().size() - 1)
          sql = sql + ", ";
      }
      sql = sql + ");\n";
    }

    if (constraint.getType() == 'U') {
      sql = sql + "ALTER TABLE " + constTableName + " ADD CONSTRAINT " + constraint.getName(true) + " UNIQUE (";

      for (int i = 0; i < constraint.getColumns().size(); i++) {
        sql = sql + constraint.getColumns().get(i).getName();
        if (i < constraint.getColumns().size() - 1)
          sql = sql + ", ";
      }
      sql = sql + ");\n";
    }

    if (constraint.getType() == 'C')
    {
      if (!constraint.getSearchCondition().endsWith("IS NOT NULL")) {
        sql = sql + "ALTER TABLE " + constTableName + " ADD CONSTRAINT " + constraint.getName(true) + " CHECK (" + constraint.getSearchCondition();

        sql = sql + ");\n";
      }
    }

    if (constraint.getType() == 'R') {
      sql = sql + "ALTER TABLE " + constTableName + " ADD CONSTRAINT " + constraint.getName(true) + " FOREIGN KEY (";

      for (int i = 0; i < constraint.getColumns().size(); i++) {
        sql = sql + constraint.getColumns().get(i).getName();
        if (i < constraint.getColumns().size() - 1)
          sql = sql + ", ";
      }
      sql = sql + ") REFERENCES " + constraint.getRefIntegritySchemaQualifiedTableName() + " (";
      for (int i = 0; i < constraint.getRefIntegrityColumns().size(); i++) {
        sql = sql + constraint.getRefIntegrityColumns().get(i).getName();
        if (i < constraint.getRefIntegrityColumns().size() - 1)
          sql = sql + ", ";
      }
      sql = sql + ") MATCH FULL ON DELETE " + constraint.getDeleteRule() + ";\n";
    }

ukr_unix_user ★★★★
()
Ответ на: комментарий от ukr_unix_user

Просто интересно, что будет быстрее работать. Когда делал для себя примитивную выгрузку объектов БД, отказался от dbms_metadata.get_ddl, т.к. работало слишком долго. Но тут ведь помимо выгрузки еще и логика по обработке результата.

winlook38 ★★
()
Ответ на: комментарий от winlook38

DBMS_METADATA используется Data Pump-ом и прочими оракловскими тулзами для использования полученных данных самим oracle. а для всяких самодельных приблуд типа oracle2other_db лучше использовать таблици из системного каталога. мне так думается.

ukr_unix_user ★★★★
()
Ответ на: комментарий от stevejobs

нз, если напишешь - выкладывай, может пригодится ещё кому.

ukr_unix_user ★★★★
()

Особенно интересен перенос структуры схем, foreign keys, etc

Чувак, перенос «схем, foreign keys, etc» должен быть однократным :-)

no-dashi ★★★★★
()
Ответ на: комментарий от stevejobs

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

no-dashi ★★★★★
()
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.