Перенесення даних з Oracle в PostgreSQL

«Ландшафт» СУБД в проектах компанії донедавна виглядав так: більшу частину становила Oracle, істотно менші — MS SQL і MySQL.

Але, як відомо, немає нічого вічного, і нещодавно до нас надійшов запит про застосовності Postgres в одному з наших проектів. До цієї СУБД ми придивлялися в останні пару років дуже пильно — відвідували конференції, meetup'и, але спробувати її в «бойових» умовах до недавнього часу не доводилося.

Отже, завдання
Дано: сервер Oracle (single instance) 11.2.0.3 і набір не пов'язаних один з одним схем загальним об'ємом ~ 50GB. Необхідно: перенести дані, індекси, первинні та посилальні ключі з Oracle в Postgres.

Вибір інструменту міграції
Огляд інструментарію для міграції показав наявність як комерційних інструментів, таких як Enterprise DB Migration Toolkit і Oracle Golden Gate, так і вільного ЗА. Переклад був запланований одноразовий, тому потрібно зріле засіб, разом з тим ясна і просте. Крім того, звичайно, враховувався і питання вартості. З вільного ЗА найбільш зрілим на сьогоднішній день є проект Ora2Pg Жиля Дарольда (Darold Gill), він  у чому перевершив функціоналу і комерційні варіанти. Переваги, що схилили чашу терезів на його бік:

  • багатий функціонал;
  • активний розвиток проекту (15 років розробки, 15 мажорних релізів).
Принцип роботи утиліти командного рядка Ora2Pg досить простий: вона з'єднується з БД Oracle, сканує вказану в файлі конфігурації схему і вивантажує об'єкти схеми в вигляді DDL-інструкцій sql-файли. Самі дані можна вивантажити в вигляді INSERT'ів sql-файл, так і вставити безпосередньо в створені таблиці СУБД Postgres.

Установка і налаштування середовища
У компанії ми використовуємо підхід DevOps для створення віртуальних машин, встановлення необхідного софта, конфігурування і розгортання. Наш робочий інструмент — Ansible. Але для того, щоб полегшити сприйняття і не вводити в статтю нові сутності, до справі не відносяться, далі ми будемо показувати ручні дії з командного рядка. Для тих, кому цікаво, ми викладаємо Ansible playbook для всіх кроків тут.

Отже, на віртуальній машині з OS Centos 6.6 виконаємо наступні кроки.

  1. Встановимо репозиторій Postgres.
  2. Встановимо Postgres 9.4 сервер.
  3. Створимо БД і налаштуємо доступ.
  4. Встановимо Postgres як сервіс і запустимо його.
  5. Встановимо instant клієнт Oracle.
  6. Встановимо утиліту Ora2Pg.
Всі подальші дії буду виробляється з-під облікового запису
root
. Встановимо репозиторій:

#yum install http://yum.postgresql.org/9.4/redhat/rhel-6-x86_64/pgdg-centos94-9.4-1.noarch.rpm

Встановимо Postgres 9.4:

#yum install postgresql94-server

Створимо кластер Postgres:

#service postgresql-9.4 initdb


Налаштування доступу зводиться до того, що ми спеціально знижуємо безпеку з'єднання Postgres для зручності тестування. Звичайно, в продакшн-середовищі ми не рекомендуємо так робити.

У файлі /var/lib/pgsql/9.4/data/postgresql.conf необхідно розкоментувати рядок
listen_addresses = '*'
. У файлі /var/lib/pgsql/9.4/data/pg_hba.conf локальних і видалених з'єднань необхідно поставити метод
trust
. Секція після редагування виглядає так:
# DATABASE USER TYPE ADDRESS METHOD

# "local" is for Unix domain socket connections only
local all all trust
# IPv4 local connections:
host all all all trust

Зареєструємо Postgres як сервіс і запустимо його:
#chkconfig postgresql-9.4 on
#service postgresql-9.4 restart

Для установки Oracle instant client необхідно завантажити з OTN наступні пакети:
oracle-instantclient11.2-basic-11.2.0.4.0-1.x86_64.rpm
oracle-instantclient11.2-devel-11.2.0.4.0-1.x86_64.rpm
oracle-instantclient11.2-sqlplus-11.2.0.4.0-1.x86_64.rpm
oracle-instantclient11.2-jdbc-11.2.0.4.0-1.x86_64.rpm

Встановимо їх:
#yum install /tmp/oracle-instantclient11.2-basic-11.2.0.4.0-1.x86_64.rpm
#yum install /tmp/oracle-instantclient11.2-devel-11.2.0.4.0-1.x86_64.rpm
#yum install /tmp/oracle-instantclient11.2-sqlplus-11.2.0.4.0-1.x86_64.rpm
#yum install /tmp/oracle-instantclient11.2-jdbc-11.2.0.4.0-1.x86_64.rpm

Створимо папку для
tnsnames.ora
:
#mkdir-p /usr/lib/oracle/11.2/client64/network/admin
#chmod 755 /usr/lib/oracle/11.2/client64/network/admin

Встановимо наступні змінні оточення (в .bash_profile користувача):
export ORACLE_HOME=/usr/lib/oracle/11.2/client64
export PATH=$PATH:$ORACLE_HOME/bin
export LD_LIBRARY_PATH=$ORACLE_HOME/lib
export TNS_ADMIN=$ORACLE_HOME/network/admin

І перевіримо працездатність.
sqlplus system/<you_password_here>@host.domain.ru/SERVICE

Якщо все ок — отримаємо приблизно такий висновок:
Connected to:
Oracle Database 11g Enterprise Edition Release 11.2.0.3.0 - 64bit Production
With the Partitioning, OLAP, Data Mining and Real Application Testing options

SQL>

Залишився останній крок налаштування — установка Ога2рд. Викачуємо з сайту останню версію Ora2Pg (на момент написання статті була версія 15.2). Встановимо необхідні пакети:
#yum install gcc cpan postgresql94-plperl postgresql94-devel

Встановимо модуль CPan:
#cpan

Встановимо додаткові модулі для Perl:
#cpan Test::Simple DBI Time::HiRes DBD::Oracle DBD::Pg

Распакуем Ora2pg в скажімо, /install:
#cd /install
#tar-xvf ora2pg-15.2.tar.gz 

Зберемо Ora2pg:
#perl Makefile.PL
#make
#make install

Міграція
СКБД Postgres по «духу» найбільш близька до Oracle. В обох добре співвідносяться типи даних, і і там є таке поняття, як схема. Скористаємося цим і будемо переносити дані «посхемно». Процес міграції буде складатися з наступних кроків.

  1. Створення проекту міграції з допомогою Ога2рд.
  2. Редагування файлу конфігурації ora2pg.conf.
  3. Вивантаження DDL таблиць, індексів, constraints з Oracle.
  4. Створення БД в Postgres.
  5. Імпорт DDL таблиць, підготовлений на 3-му кроці.
  6. Копіювання даних.
  7. Імпорт DDL індексів і constraints.
Всі подальші дії будемо виконувати від користувача postgres.
#su-l postgres

Створимо проект міграції. Проект складається з набору папок tables/functions/views/packages, в яких будуть знаходиться sql-файли з DDL відповідних об'єктів, конфігураційного файлу ora2pg.conf і скрипта запуску — export_schema.sh.
$ora2pg --init_project my_project_name
$cd my_project_home
$vi config/ora2pg.conf

Налаштування
Файл конфігурації Ora2pg досить об'ємний, і я зупинюся тільки на тих параметрах, які є кореневими або знадобилися під час міграції наших даних. Про решту я рекомендую дізнатися з цієї статті.

Секція, яка описує параметри з'єднання c БД Oracle:
ORACLE_HOME /usr/lib/oracle/11.2/client64
ORACLE_DSN dbi:Oracle:host=oracle_host.domain.ru;sid=<SID>
ORACLE_USER SYSTEM
ORACLE_PWD MANAGER

Секція, що описує, яку схему вивантажуємо:
EXPORT_SCHEMA 1
SCHEMA TST_OWNER

І вказівку, яку схему завантажуємо:
PG_SCHEMA tst_owner

Вказуємо тип експорту. Параметр
COPY
говорить про те, що ми будемо копіювати дані напряму з Oracle в Postgres, минаючи текстовий файл.
TYPE TABLE,COPY

Секція, яка описує параметри з'єднання c БД Postgres:
PG_DSN dbi:Pg:dbname=qqq;host=localhost;port=5432
PG_USER tst_owner
PG_PWD tst_onwer

Секція конвертації типів даних. Для того, щоб тип
number()
без вказівки точності не конвертувався в 
bigint
, зазначимо:
DEFAULT_NUMERIC numeric

На цьому конфігураційні кроки закінчені, і ми готові приступити до переносу. Вивантажимо опису схеми в вигляді набору sql-файлів c DDL об'єктів:
$./export_schema.sh

Створимо базу даних qqq, користувача test_owner і видамо необхідні права.
$psql 
postgres=#create database qqq;
CREATE DATABASE
postgres=#create user test_owner password 'test_owner';
CREATE ROLE
postgres=#grant all on database qqq to test_owner;
GRANT
postgres=#\q

Виконаємо імпорт sql-файл c DDL таблиць
$psql-d qqq-U test_owner < schema/tables/table.sql

Тепер все готово до копіювання даних. Запускаємо:
$ora2pg-t COPY-o data.sql-b ./data-c ./config/ora2pg.conf

Незважаючи на той факт, що в командному рядку ми вказуємо параметр з іменем файла, який слід зберігати вивантаження, вставка даних відбувається безпосередньо з Oracle в Postgres. У нашому випадку швидкість вставки була близько 6 тис. рядків у секунду, але це, звичайно ж, залежить від типів копійованих даних і навколишньої інфраструктури.

Залишився останній крок — створити індекси і constraints.
$psql-d qqq-U test_owner < schema/tables/INDEXES_table.sql
$psql-d qqq-U test_owner < schema/tables/CONSTRAINTS_table.sql

Якщо у процесі виконання попередніх команд ви не отримали помилок — вітаю, міграція пройшла успішно! Але, як відомо з закону Мерфі: «Anything that can go wrong will go wrong».

Наші підводні камені
Перший підводний камінь уже був згаданий вище: тип
number()
без вказівки точності конвертується в
bigint
, але це легко виправити правильною конфігурацією.

Наступною складністю виявилося те, що в Postgres немає типу, аналогічного Oracle anydata. У зв'язку з цим ми були змушені, проаналізувавши і поправивши логіку програми, в шкоду гнучкості сконвертувати його в «підходящі» типи, наприклад, в 
varchar2(100)
. Крім того, якщо у вас є якісь кастомні типи, то все доведеться переробляти, оскільки вони не транслюються, але це тема як мінімум для окремої статті.

Підведемо підсумки
Утиліта Ora2Pg, незважаючи на складність настройки, проста і надійна в використанні. Її сміливо можна рекомендувати для міграції невеликих і середніх БД. До речі, її автор на PGConf Russia оголосив про те, що починає проект MS2Pg. Звучить багатообіцяюче.

Вдалих міграцій!

Джерело: Хабрахабр

0 коментарів

Тільки зареєстровані та авторизовані користувачі можуть залишати коментарі.